WPF-父ViewModel中的子datacontext集不包含父ViewModel中已修改的值
在我的WPF应用程序中,我有一个MainWindow.xaml,其中嵌入了许多用户控件。主窗口和用户控件都有单独的viewmodel。在主窗口ViewModel中,我创建了子ViewModel的一个实例,并将其设置为子视图的datacontext 父虚拟机 ChildUserControlVM ChildVM=新的ChildUserControlVM(ParentModel.ChildModel) MainWindow.xamlWPF-父ViewModel中的子datacontext集不包含父ViewModel中已修改的值,wpf,mvvm,user-controls,Wpf,Mvvm,User Controls,在我的WPF应用程序中,我有一个MainWindow.xaml,其中嵌入了许多用户控件。主窗口和用户控件都有单独的viewmodel。在主窗口ViewModel中,我创建了子ViewModel的一个实例,并将其设置为子视图的datacontext 父虚拟机 ChildUserControlVM ChildVM=新的ChildUserControlVM(ParentModel.ChildModel) MainWindow.xaml <Grid Grid.Row="0" HorizontalA
<Grid Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0">
<local:ProfileIdentitySettings Visibility="{Binding ProfileIdentitySettingsVisibility,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" DataContext="{Binding ChildProfileIdentityVM}"/>
</Grid>
但是这种方法不起作用,因为我没有在子视图模型中获取父视图模型中设置的值,反之亦然
相反,如果我将子模型对象设置为双向工作的父对象的datacontext
我需要一些解决方案,以便在用户控件中使用MVVM,同时确保数据从父级传递到子级,反之亦然。
在usercontrol中,我将有一些按钮,我希望通过ICommand在子Viewmodel中处理这些按钮的操作。
添加代码片段以供参考
MainWindow.xaml
<Grid Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0">
<local:ProfileIdentitySettings Visibility="{Binding ProfileIdentitySettingsVisibility,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" DataContext="{Binding ChildProfileIdentityVM}"/>
</Grid>
ProfileIdentitySettings.xaml
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.MainWindowVM}">
在xaml中设置每个usercontrol的datacontext
<UserControl.DataContext>
<VMPath:ChildVM/>
</UserControl.DataContext>
如果您需要执行的操作总是相同的,那么可以对所有UserControl使用1方法
基本上你要做的是下面的操作
- 将用户控件的文本静态设置为“空”ChildVM的实例
- 加载控件
- 加载后,在ChildVM上执行需要执行的操作(如设置一些属性)
在实际使用应用程序之前,所有这些都应包含子视图模型作为属性,如
public class ParentViewModel
{
public ChildViewModel1 ChildViewModel1 { get; set; }
public ChildViewModel2 ChildViewModel2 { get; set; }
}
用户控件不应该有自己的任何视图模型。相反,它们应该公开依赖项属性,如
public partial class MyView1 : UserControl
{
public string MyProperty { get; set; } // this must be a dependency property
}
在使用UserControl时可以绑定,例如在主窗口的XAML中,如
<MyView1 MyProperty="{Binding ChildViewModel1.SomeProperty}" />
如果存在许多这些可绑定属性,则可以将UserControl的DataContext设置为适当的子视图模型:
<MyView1 DataContext="{Binding ChildViewModel1}"
MyProperty="{Binding SomeProperty}" />
我的理解是,您需要从MainViewModel设置usercontrol Viewmodel MainViewModel:
public class MainWindowViewModel : INotifyPropertyChanged, IMainViewModel
{
public MainWindowViewModel()
{
this.Collection = new List<string>();
this.Child = new ChildUserControlViewModel();
this.Child.mainViewModel = this;
this.Child.TextValue = "Justin";
}
private List<string> _Collection;
public List<string> Collection
{
get { return _Collection; }
set { _Collection = value; this.OnPropertyChanged("Collection"); }
}
private string _MainValue;
public string MainValue
{
get { return _MainValue; }
set { _MainValue = value; this.OnPropertyChanged("MainValue"); }
}
private ChildUserControlViewModel child;
public ChildUserControlViewModel Child
{
get { return child; }
set { child = value; this.OnPropertyChanged("Child"); }
}
}
public类MainWindowViewModel:INotifyPropertyChanged,IMainViewModel
{
公共主窗口视图模型()
{
this.Collection=新列表();
this.Child=新的ChildUserControlViewModel();
this.Child.mainViewModel=此;
this.Child.TextValue=“Justin”;
}
私人收藏清单;
公共列表集合
{
获取{return\u Collection;}
设置{u Collection=value;this.OnPropertyChanged(“Collection”);}
}
私有字符串_main值;
公共字符串main值
{
获取{return\u MainValue;}
设置{u MainValue=value;this.OnPropertyChanged(“MainValue”);}
}
private ChildUserControlViewModel子级;
公共子项UserControlViewModel子项
{
获取{return child;}
设置{child=value;this.OnPropertyChanged(“child”);}
}
}
子用户控件视图模型:
public class ChildUserControlViewModel : INotifyPropertyChanged
{
public IMainViewModel mainViewModel = null;
public List<string> Collection
{
get { return this.mainViewModel.Collection; }
set { this.mainViewModel.Collection = value; this.OnPropertyChanged("Collection"); }
}
private string _TextValue;
public string TextValue
{
get { return _TextValue; }
set
{
_TextValue = value;
this.mainViewModel.MainValue = value;
this.mainViewModel.Collection.Add(value);
this.OnPropertyChanged("TextValue");
}
}
}
public interface IMainViewModel
{
string MainValue { get; set; }
List<string> Collection { get; set; }
}
公共类ChildUserControlViewModel:INotifyPropertyChanged
{
public IMainViewModel mainViewModel=null;
公共列表集合
{
获取{返回this.mainViewModel.Collection;}
设置{this.mainViewModel.Collection=value;this.OnPropertyChanged(“Collection”);}
}
私有字符串_TextValue;
公共字符串文本值
{
获取{return\u TextValue;}
设置
{
_TextValue=值;
this.mainViewModel.MainValue=值;
this.mainViewModel.Collection.Add(value);
此.OnPropertyChanged(“TextValue”);
}
}
}
公共接口IMainViewModel
{
字符串MainValue{get;set;}
列表集合{get;set;}
}
视图:
你能展示你的代码吗?我已经添加了代码片段。此操作当前不起作用。请不要执行此操作。从不设置UserControl的DataContext是一种反模式。它有效地防止控件的属性绑定到继承的DataContext,这是您通常希望发生的事情。尽管互联网上的许多“WPF专家”告诉你,设置UserControl的DataContext不可避免地会让你陷入麻烦。@Clemens OP没有给我们提供很多细节,但据我所知,ChildVM是一个不同的viewmodel。因此,实际上OP的usercontrols只需要由主windows datacontext设置一些属性,而不需要继承它的datancontext。我只是提出了一个简单的方法,设置UserControl的DataContext总是错误的。参见例如,或。您在这里给出了一个非常糟糕的建议。@克莱门斯,如果OP需要将其用户控件用于不同的视图模型,这将是一个非常糟糕的建议。在这里,我想我看到的99%的问题(特别是来自newst用户)都是用几个强耦合的视图/视图模型来投影他们的应用程序,我认为这种情况也不例外。然而,如果不是这样的话,您的答案也是不好的(除非ChildVM真的从ParentVM继承)。如果它们是独立的视图模型,我想你应该做的是完全友好地使用MVVM,我不是在谈论应用程序和它们的主窗口。当然,您将在那里设置视图模型。然而,这里有相当多的人(包括我)经常回答诸如“为什么我的UserControl绑定不起作用”之类的问题。通常是因为提问者犯了上述错误。不管你谈论它多久,它仍然是错误的。我们在这里已经讨论了上千次了……我已经读过你关于不在UC中使用viewModels的评论。听起来不错,但是当您设置DataContext=“{Binding ChildViewModel1}”时,您将如何重用这样的UC?Sasha他正在主窗口中这样做,以便MyView1(UC)可以与其他ViewModels一起重用该行
public class MainWindowViewModel : INotifyPropertyChanged, IMainViewModel
{
public MainWindowViewModel()
{
this.Collection = new List<string>();
this.Child = new ChildUserControlViewModel();
this.Child.mainViewModel = this;
this.Child.TextValue = "Justin";
}
private List<string> _Collection;
public List<string> Collection
{
get { return _Collection; }
set { _Collection = value; this.OnPropertyChanged("Collection"); }
}
private string _MainValue;
public string MainValue
{
get { return _MainValue; }
set { _MainValue = value; this.OnPropertyChanged("MainValue"); }
}
private ChildUserControlViewModel child;
public ChildUserControlViewModel Child
{
get { return child; }
set { child = value; this.OnPropertyChanged("Child"); }
}
}
public class ChildUserControlViewModel : INotifyPropertyChanged
{
public IMainViewModel mainViewModel = null;
public List<string> Collection
{
get { return this.mainViewModel.Collection; }
set { this.mainViewModel.Collection = value; this.OnPropertyChanged("Collection"); }
}
private string _TextValue;
public string TextValue
{
get { return _TextValue; }
set
{
_TextValue = value;
this.mainViewModel.MainValue = value;
this.mainViewModel.Collection.Add(value);
this.OnPropertyChanged("TextValue");
}
}
}
public interface IMainViewModel
{
string MainValue { get; set; }
List<string> Collection { get; set; }
}
<Grid>
<usr:ChildUserControl DataContext="{Binding Child}"/>
</Grid>