gpt4 book ai didi

.net - 确保每个子 UserControl 创建自己的 ViewModel 实例

转载 作者:行者123 更新时间:2023-12-02 01:52:46 24 4
gpt4 key购买 nike

我正在为客户开发一个项目,并决定利用 WPF 在数据绑定(bind)和 UI 设计的声明性方法方面的优势。但是我在理解我的 View 和 View 模型之间的关系时遇到了一个大问题。

我有一个用户控件 (ParentUserControl) 和一个子用户控件 (ChildUserControl)。在这个 ParentUserControl 中,我有一个 ContentPresenter,它可以容纳 ChildUserControl 的多个实例。 ChildUserControl 有多个组合框和文本框显示来 self 的模型的信息。用户可以通过单击“添加新”按钮在 ParentUserControl 中打开任意数量的 ChildUserControl。在我的 ParentViewModel 中,我存储了与用户一起创建的每个 ChildViewModel 的实例,将新的 ChildUserControl 添加到 ParentUserControl。用户可以通过“查看下一个”和“查看上一个”按钮在 ChildUserControl 中导航。

所有这一切都很好,除非用户在任何 ChildUserControl 中进行选择或更改任何控件的文本,更改会传播到用户创建的所有 ChildUserControl/为所有 View 共享一个 ViewModel。我已经尝试了所有我能想到的方法,无论是否使用 MVVM Light 工具包(这似乎会在未来为我节省大量时间)。

我的问题是,我如何才能绝对肯定地确定每次实例化新 View 时它都会获得自己的 ViewModel 实例?我已经坚持了好几天了!!!谢谢!

'注意:此代码不是实际产品。这是为了简单地演示我在实际应用程序中遇到的问题。如果需要,不要害怕用 C# 回答,无论如何我的首选语言。哦,我正试图在考虑 Pure MVVM 的情况下完成这个项目。谢谢!!!

代码:

父用户控件:

<UserControl x:Class="ParentUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MVVM_Light_Test_Application"
Height="350" Width="525">
<UserControl.Resources>
<DataTemplate DataType="{x:Type local:ChildUserControlViewModel}">
<local:ChildUserControl/>
</DataTemplate>
</UserControl.Resources>

<UserControl.DataContext>
<local:MainViewModel/>
</UserControl.DataContext>
<Grid>
<StackPanel Width="auto" Height="200">
<ContentPresenter Content="{Binding CurrentView}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
</ContentPresenter>
</StackPanel>
<StackPanel>
<Button Command="{Binding ChangeUserControlCommand}" Content="Click To Change View"/>
</StackPanel>
</Grid>
</UserControl>

子用户控件:

<UserControl x:Class="ChildUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MVVM_Light_Test_Application"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="{Binding BGColor, UpdateSourceTrigger=PropertyChanged}">
<UserControl.DataContext>
<local:ChildUserControlViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="149*"/>
<ColumnDefinition Width="151*"/>
</Grid.ColumnDefinitions>

<StackPanel Height="200" Width="auto">
<StackPanel>
<ComboBox x:Name="cboExampleObjects" Margin="5" ItemsSource="{Binding Customers}" DisplayMemberPath="Details" SelectedItem="{Binding SelectedCustomer}"/>
</StackPanel>
<StackPanel Grid.Column="1">
<TextBox x:Name="txtObjectPropertyValue" Text="{Binding SelectedCustomer.Name}" Margin="5"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>

父 View 模型:

Public Class MainViewModel
Inherits ViewModelBase

Public Sub New()
_currentView = New ChildUserControlViewModel
ChangeUserControlCommand = New RelayCommand(AddressOf ChangeUserControl)
End Sub

Private _currentView As ViewModelBase
Public Property CurrentView As ViewModelBase
Get
Return _currentView
End Get
Set(value As ViewModelBase)
_currentView = value
RaisePropertyChanged("CurrentView")
End Set
End Property

Public Property ChangeUserControlCommand As RelayCommand


Public Sub ChangeUserControl()
CurrentView = New ChildUserControlViewModel
CType(CurrentView, ChildUserControlViewModel).BGColor = Nothing
End Sub
End Class

subview 模型:

导入 System.Collections.ObjectModel

Public Class ChildUserControlViewModel
Inherits ViewModelBase

Public Sub New()
_customes = New ObservableCollection(Of Customer)(New List(Of Customer)({New Customer With {.Name = "TestName1", .CustomerNumber = 1}, New Customer With {.Name = "TestName2", .CustomerNumber = 2}}))
End Sub

Private _customers As ObservableCollection(Of Customer)
Public Property Customers As ObservableCollection(Of Customer)
Get
Return _customers
End Get
Set(value As ObservableCollection(Of Customer))
_customers = value
RaisePropertyChanged("Customers")
End Set
End Property

Private _selectedCustomer As Customer
Public Property SelectedCustomer As Customer
Get
Return _selectedCustomer
End Get
Set(value As Customer)
If _selectedCustomer Is Nothing OrElse String.Compare(value.Name, _selectedCustomer.Name) <> 0 Then
_selectedCustomer = value
RaisePropertyChanged("SelectedCustomer")
End If
End Set
End Property

Private _bgColor As SolidColorBrush
Public Property BGColor As SolidColorBrush
Get
Dim random As New Random
Return New SolidColorBrush(Color.FromArgb(50, Random.Next(0, 255), Random.Next(0, 255), Random.Next(0, 255)))
End Get
Set(value As SolidColorBrush)
Dim random As New Random
_bgColor = New SolidColorBrush(Color.FromArgb(50, random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)))
RaisePropertyChanged("BGColor")
End Set
End Property
End Class

最佳答案

我看到几个问题:

  1. 您在 XAML 中设置了 ChildUserControl.DataContext,但是 ChildUserControl 的实例已经从 ContentPresenter 中的绑定(bind)中获取了数据上下文。您可以安全地删除它。

  2. ContentPresenter 只能包含一个 子控件。当您创建一个新的 View 模型并将其设置为 CurrentView 时,旧的 View 模型被遗忘,旧的 ChildUserControl 被删除,然后是一个新的 ChildUserControl 已创建,代表新的 View 模型。

您如何在 subview 之间导航?我没有看到相关代码。

关于.net - 确保每个子 UserControl 创建自己的 ViewModel 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21820607/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com