本文介绍了WPF - 如何确保每个视图都有自己的ViewModel实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我对WPF和MVVM模式都很陌生,所以请光临我。我为客户开发项目,并决定在数据绑定和UI设计的声明方法方面利用WPF的优势。但是我在理解我的Views和ViewModel之间的关系时遇到了很大的问题。 我有一个UserControl(ParentUserControl)和一个子UserControl(ChildUserControl)。在这个ParentUserControl中,我有一个ContentPresenter,可以容纳ChildUserControl的多个实例。 ChildUserControl有多个组合框和文本框,显示我的模型中的信息。用户可以通过单击添加新按钮,在ParentUserControl中打开尽可能多的ChildUserControl。在我的ParentViewModel中,我存储了用户创建的每个ChildViewModel的实例,并将新的ChildUserControl添加到ParentUserControl。用户可以通过查看下一个和查看上一个按钮浏览ChildUserControl。 所有这些都很有效,除非用户进行选择或更改任何ChildUserControl中的任何控件的文本,更改都会传播到用户为所有视图创建/共享一个ViewModel的所有ChildUserControl。无论使用和不使用MVVM Light工具包,我都尝试了所有我能想到的东西(这似乎将来会节省我很多时间)。 *我的问题是,我怎样才能绝对肯定每次实例化新视图时它都会获得自己的ViewModel实例?我已经坚持了几天!!!谢谢!* '注意:此代码不是实际产品。这只是为了演示我在实际应用程序中遇到的问题。如果需要,不要害怕用C#回答,无论如何我是首选的语言。哦,我正在尝试用Pure MVVM完成这个项目。谢谢!!! 代码: ParentUserControl: < 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 高度 = 350 宽度 = 525 > < UserControl.Resources > < DataTemplate DataType = {x:Type local:ChildUserControlViewModel} > < local:ChildUserControl / > < / DataTemplate > < /UserControl.Resources > < UserControl。 DataContext > < local:MainViewModel / > < / UserControl.DataContext > < 网格 > < StackPanel 宽度 = auto 高度 = 200 > < ContentPresenter 内容 = {Binding CurrentView} HorizontalAlignment = 拉伸 VerticalAlignment = 拉伸 > < / ContentPresenter > < / StackPanel > < StackPanel > < 按钮 命令 = {Binding ChangeUserControlCommand} 内容 = 点击更改视图 / > < / StackPanel > < / Grid > < / UserControl > ChildUserControl: < 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:可忽略 = d d:DesignHeight = 300 d:DesignWidth = 300 已移除 = {Binding BGColor,UpdateSourceTrigger = PropertyChanged} > < UserControl.DataContext > < local:ChildUserControlViewModel / > < / UserControl.DataContext > < 网格 > < Grid.ColumnDefinitions > < ColumnDefinition 宽度 = 149 * / > < ColumnDefinition 宽度 = 151 * / > < / Grid.ColumnDefinitions > < StackPanel 高度 = 200 宽度 = auto > < StackPanel > < ComboBox x:名称 = cboExampleObjects 保证金 = 5 ItemsSource = {绑定客户} DisplayMemberPath = 详细信息 SelectedItem = {Binding SelectedCustomer} / > < / StackPanel > < StackPanel Grid.Column = 1 > < TextBox x:名称 = txtObjectPropertyValue 文字 = {Binding SelectedCustomer.Name} 保证金 = 5 / > < / StackPanel > < / StackPanel > < / Grid > < / UserControl > 父母视图型号: 公共 类 MainViewModel 继承 ViewModelBase 公共 Sub 新() _currentView = 新 ChildUserControlViewModel ChangeUserControlCommand = 新 RelayCommand( AddressOf ChangeUserControl) 结束 Sub 私有 _currentView 作为 ViewModelBase 公共 属性 CurrentView 作为 ViewModelBase 获取 返回 _currentView 结束 获取 设置(值 As ViewModelBase) _currentView = value RaisePropertyChanged( CurrentView ) 结束 设置 结束 属性 公共 属性 ChangeUserControlCommand As RelayCommand 公共 Sub ChangeUserControl() CurrentView = 新 ChildUserControlViewModel CType (CurrentView,ChildUserControlViewModel).BGColor = Nothing End Sub 结束 类 儿童景观型号: Imports System.Collections.ObjectModel Public Class ChildUserControlViewModel 继承 ViewModelBase 公共 Sub New () _customes = 新 ObservableCollection( 客户)(新列表( 客户)({新客户使用 {.Name = TestName1,。CustomerProumber = 1 },新客户使用 {。Name = TestN ame2,。CustomerProumber = 2 }})) 结束 Sub 私有 _customers As ObservableCollection( 客户) 公共 属性客户作为 ObservableCollection( 客户) 获取 返回 _customers 结束 获取 设置(值 As ObservableCollection ( 客户)) _customers = value RaisePropertyChanged( Customers) End 设置 结束 属性 私人 _selectedCustomer 作为客户 公开 属性 SelectedCustomer 作为客户 获取 返回 _selectedCustomer 结束 获取 设置(值 As Customer) 如果 _selectedCustomer 没什么 OrElse String .Compare(value.Name,_selectedCustomer.Name)<> 0 然后 _selectedCustomer = value RaisePropertyChanged( SelectedCustomer) 结束 如果 结束 设置 结束 属性 私有 _bgColor 作为 SolidColorBrush 公共 属性 BGColor As SolidColorBrush 获取 Dim random As 新随机 返回 新 SolidColorBrush(Color.FromArgb( 50 ,Random。 Next ( 0 , 255 ),随机。下一步( 0 , 255 ),随机。下一步( 0 , 255 ))) 结束 获取 设置(值 As SolidColorBrush) Dim random As 新随机 _bgColor = 新 SolidColorBrush(颜色。 FromArgb( 50 ,随机。下一步( 0 , 255 ),随机。下一步( 0 , 255 ),随机。下一步( 0 , 255 ))) RaisePropertyChanged( BGColor) 结束 设置 结束 属性 结束 类 解决方案 SO上的优秀绅士为我回答了我的问题。在绑定到ContentPresenter时,我没有意识到子视图为它们设置了数据上下文。一旦我删除了< usercontrol.datacontext>来自ChildUserControl的标签,一切都像梦一样。要查看我收到的答案,请单击 此处 [ ^ ] I am quite new to WPF and the MVVM pattern so please bare with me. I working on a project for a client and decided to utilize the benefits of WPF in terms of data binding and the declarative approach to UI design. But I'm having a huge issue understanding the relationship between my Views and ViewModels.I have a UserControl (ParentUserControl), and a child UserControl (ChildUserControl). Within this ParentUserControl I have a ContentPresenter that can hold multiple instances of ChildUserControl. The ChildUserControl has multiple comboboxes and textboxes displaying information from my Model. The user can open as many ChildUserControls within the ParentUserControl as they wish by clicking an 'Add New' Button. In my ParentViewModel, I'm storing the instances of each ChildViewModel that is created with the user adds a new ChildUserControl to the ParentUserControl. The user can navigate through the ChildUserControls through 'View Next' and 'View Previous' Buttons.All of this works great, except if a user makes a selection or changes the text of any control in any ChildUserControl, the change propagates throughout all the ChildUserControls the user has created / sharing one ViewModel for all views. I've tried everything that I can think of, with and without using the MVVM Light tool kit (which seems like it's going to save me a ton of time in the future).*My question is how can I be absolutely positively sure that each time a new View is instantiated that it gets its own instance of it's ViewModel? I've been stuck on this for days!!! Thanks!*'NOTE: This code is not of an actual product. It's to simply demonstrate the issue I'm having with a real application. Don't be afraid to answer in C# if need be, my preferred language anyway. Oh, and I'm trying to complete this project with Pure MVVM in mind. Thank you!!!Code:ParentUserControl:<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>ChildUserControl:<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" removed="{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>Parent View Model: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 ClassChild View Model:Imports 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 解决方案 A fine gentleman on SO answered my question for me. I did not realize that the child views had their data context set for them when binding to the the ContentPresenter. Once I removed the <usercontrol.datacontext> tag from the ChildUserControl, everything worked like a dream. To view the answer I received click Here [^] 这篇关于WPF - 如何确保每个视图都有自己的ViewModel实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-13 20:35