将代码后面的数据和ViewModel传递给另一个ViewModel

时间:2016-07-29 17:44:50

标签: xaml mvvm viewmodel

我有一个View,它有2个子视图,ViewModel分配给每个视图:

ViewParent - ViewModelParent
{ 
   ViewA - ViewModelA
   ViewB - ViewModelB
}

ViewParent结构如下所示。

<StackPanel Orientation="Vertical">
    <local:AView DataContext="{Binding ViewModelA, Mode=TwoWay}"></localViews:AView>
</StackPanel>
<StackPanel Orientation="Vertical">
    <localViews:BView DataContext="{Binding ViewModelB, Mode=TwoWay}"></localViews:BView>
</StackPanel>

现在在ViewA后面的代码中,我有一个事件要在gridview中选择一行。

  private void radGridView_SelectionChanged(object sender, SelectionChangeEventArgs e)
    {
        try
        {
            RadGridView grv = sender as RadGridView;                       

            if (e.AddedItems.Count > 0)
            {
               var row = grv.SelectedItem as SomeClass;
               if(condition)
                  // Enable a button in ViewB.

我想要的是将row传递给ViewModelB。另外,我想在ViewB中启用一个按钮。最后,我想将ViewModelA中的几个整数传递给ViewModelB

怎么做?我考虑过构造函数注入,但仍然没有明确的想法。

1 个答案:

答案 0 :(得分:1)

这里有很多打字,但没有困难的逻辑,没有任何东西可以变成一个错误并咬你。

  1. 确保ParentViewModel引用ViewModelAViewModelB(据我所知,您已经在那里)。

  2. ViewModelA SelectedRowChanged个事件:

    public event EventHandler SelectedRowChanged;
    
  3. ViewModelB提供IsMyButtonEnabled属性(但请将其命名为更好;您需要使用名称来指示指的是哪个按钮)

    private bool _isMyButtonEnabled;
    public bool IsMyButtonEnabled {
        get { return _isMyButtonEnabled; }
        set { 
            _isMyButtonEnabled = value;
            OnPropertyChanged(nameof(IsMyButtonEnabled));
        }
    }
    
  4. ViewB中,将按钮的IsEnabled属性绑定到该属性:

    <Button
        ...
        IsEnabled="{Binding IsMyButtonEnabled}"
        ...
    
  5. 同时为ViewModelAViewModelB提供SelectedRow属性。

    private SomeClass _selectedRow;
    public SomeClass SelectedRow {
        get { return _selectedRow; }
        set { 
            _selectedRow = value;
            OnPropertyChanged(nameof(SelectedRow));
            /*
                DO ADDITIONAL STUFF HERE:
    
                VMA: 
                    SelectedRowChanged?.Invoke(this, EventArgs.Empty);
    
                VMB:
                    Set IsMyButtonEnabled to whatever is appropriate based on
                    the selected row. 
             */
        }
    }
    
  6. ParentViewModelViewModelA.SelectedRowChanged设置了一个处理程序,它可以执行此操作,因为它具有对其ViewModelA实例的引用。然后处理程序告诉ViewModelB做一些在SelectedRow更改时需要完成的事情。另一种方法是为ViewModelB提供ViewModelA的引用,并让它处理ViewModelA.SelectedRowChanged。但作为一项规则,您希望您的子视图模型比这更松散耦合。你不希望B 依赖有一个类型A的兄弟。但是父已经取决于拥有这两个孩子。一分钱,一磅。你不能再弄湿了。

    ...
    //  Constructor or someplace
    this.VMA = new ViewModelA();
    this.VMA.SelectedRowChanged += ViewModelA_SelectedRowChanged;
    ...
    
    void ViewModelA_SelectedRowChanged(Object sender, EventArgs e)
    {
        //  VMB.SelectedItem's setter will enable the button appropriately
        VMB.SelectedItem = VMA.SelectedItem;
    }
    
  7. 你真的应该&#34;应该&#34;使用Command执行按钮操作,并启用Command而不是具有Is*ButtonEnabled属性。这是一种更通用,更强大的做事方式。但我们可以一步一步走。