WPF - 从父 ViewModel 设置的子数据上下文不包含父 ViewModel 中的修改值

WPF -Child datacontext set from the parent ViewModel doesnot contains the modified values in the parent ViewModel

在我的 WPF 应用程序中,我有一个 MainWindow.xaml,其中嵌入了许多用户控件。我对主要 window 和用户控件都有单独的视图模型。在 Main Window ViewModel 中,我创建了子 ViewModel 的实例并将其设置为子 ViewModel 的数据上下文。

父虚拟机 ChildUserControlVM ChildVM = new ChildUserControlVM (ParentModel.ChildModel);

MainWindow.xaml

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

相反,如果我将子模型对象设置为双向工作的父模型对象的数据上下文。

我需要一些解决方案,以便我可以在用户控件中使用 MVVM,同时确保数据从父级传递到子级,反之亦然。 在用户控件中,我将有一些按钮,我想通过 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>

MainWindowVM.cs

 ProfileIdentitySettingsVM ChildProfileIdentityVM = new ProfileIdentitySettingsVM(DeviceEditorModel.ProfileIdentitySettings);

ProfileIdentitySettings.xaml

DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.MainWindowVM}">

在 xaml

中设置每个用户控件的数据上下文
<UserControl.DataContext>
    <VMPath:ChildVM/>
</UserControl.DataContext>

然后为 MainWindow 中定义的用户控件添加加载事件

<ViewPath:MyUserControl x:Name="uc1" Loaded="UserControlLoaded"/>

在您后面的代码中,您将拥有

    private void UserControlLoaded(object sender, RoutedEventArgs e)
    {
        ParentVM vm = this.DataContext as VM;
        ChildVM cvm = uc1.DataContext as ChildVM;
        // do your stuff
    }

如果您需要执行的操作始终相同,您可以对所有 UserControl 使用 1 种方法。

基本上你要做的就是下面的操作

  • 将用户控件的 dantacontext 静态设置为 "empty" 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时可以绑定,例如在你的 MainWindow 的 XAML,比如

<MyView1 MyProperty="{Binding ChildViewModel1.SomeProperty}" />

如果有很多这样的可绑定属性,您可以将 UserControl 的 DataContext 设置一次到适当的子视图模型:

<MyView1 DataContext="{Binding ChildViewModel1}"
         MyProperty="{Binding SomeProperty}" />

我的理解是您需要从 MainViewModel 设置 usercontrol Viewmodel。

主视图模型:

 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>