如何在主视图模型和用户控件视图模型之间进行通信

时间:2020-07-09 08:53:30

标签: c# wpf xaml mvvm data-binding

我有一个主视图模型,并根据情况加载了一些用户控件(稳定性,坦克)。这些用户控件具有诸如StabilityVM,TankVM之类的视图模型。我的问题是如何将数据从主视图模型发送到用户控件视图模型,反之亦然。我的main.xaml及其视图模型如下所示

主窗口xaml部分

<ContentControl  Grid.Row="1" Content="{Binding 
ActiveUserControl,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type vm:TankVM}">
                <uc:Tank></uc:Tank>
            </DataTemplate>
            <DataTemplate DataType="{x:Type vm:StabilityVM}">
                <uc:Stability></uc:Stability>
            </DataTemplate>
        </ContentControl.Resources>

    </ContentControl>

主视图模型零件

public class MainVM : INotifyPropertyChanged
{
    Stability stability;
    Tank tank;
    WeightItem weightItem;
  
    public List<Grid> myControls = new List<Grid>();
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


    private UserControl activeUserControl;

    public UserControl ActiveUserControl
    {
        get { return activeUserControl; }
        set { activeUserControl = value;
            OnPropertyChanged(nameof(ActiveUserControl));
        }
    }

    public MainVM()
    {
        //First user control class
        stability = new Stability();
        stability.Visibility = Visibility.Visible;
        //Second user control class
        tank = new Tank();
        tank.Visibility = Visibility.Visible;

        ActiveUserControl = stability;
        ActiveUserControl.Visibility = Visibility.Visible;
        
    }
}

1 个答案:

答案 0 :(得分:0)

要在视图模型之间进行通信,可以使用mediator patternCaliburn.MicroPrism之类的许多WPF应用程序框架都提供了此模式的具体实现,因此您不必自己实现它。两者都提供了一个所谓的事件聚合器,用于通过松耦合事件进行通信。

例如,在Prism中,您将定义一个带有或不带有事件参数的事件类型。

// Events derive from PubSubEvent or PubSubEvent<T> if you use event aruments
public class TankChangedEvent : PubSubEvent<TankChangedEventArgs>
{
}

// Event arguments for the above event, uses a property to capture the changed tank
public class TankChangedEventArgs
{
    public Tank Tank { get; }

    TankChangedEventArgs(Tank tank)
    {
        Tank = tank;
    }
}

然后在发送者视图模型中,使用事件聚合器发布事件。请注意,您需要创建或注入事件聚合器的实例eventAggregator

var args = new TankChangedEventArgs(changedTank);
eventAggregator.GetEvent<PartsDeletedEvent>().Publish(args);

在接收视图模型中,您需要订阅事件,例如在构造函数中。

eventAggregator.GetEvent<LogicalDirectoriesChangedEvent>().Subscribe(OnTankChanged);

创建方法OnTankChanged来处理收到的事件。

private void OnLogicalDirectoriesChanged(TankChangedEventArgs args)
{
    // Do something with the event arguments
}

您可以详细了解here。有关Caliburn Micro的示例,请参考this site。尽管这些机制内置于相应的框架中,但是您也可以在项目中单独使用它们,而无需迁移整个应用程序。但是,还有其他实现,但是这些框架是一个很好的起点,因为它们具有关于该主题的全面文档。