WPF-父ViewModel中的子datacontext集不包含父ViewModel中已修改的值

WPF-父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

在我的WPF应用程序中,我有一个MainWindow.xaml,其中嵌入了许多用户控件。主窗口和用户控件都有单独的viewmodel。在主窗口ViewModel中,我创建了子ViewModel的一个实例,并将其设置为子视图的datacontext

父虚拟机 ChildUserControlVM ChildVM=新的ChildUserControlVM(ParentModel.ChildModel)

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>

但是这种方法不起作用,因为我没有在子视图模型中获取父视图模型中设置的值,反之亦然

相反,如果我将子模型对象设置为双向工作的父对象的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>