简体   繁体   中英

How to communicate between main view model and user control view model

I have a main view model and it loads some user controls (Stability,Tank) according to some cases. Those user controls have view models like StabilityVM, TankVM. My question is that how to send data from main view model to user control view model or vice versa. My main.xaml and its view model are shown below

Main window xaml part

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

Main View Model Part

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;
        
    }
}

To communicate between view models you can use the mediator pattern . Many WPF application frameworks like Caliburn.Micro or Prism offer a concrete implementation of this pattern, so you do not have to implement it yourself. Both of them offer a so-called event aggregator for communicating via loosely-coupled events.

As an example, in Prism you would define an event type with or without event arguments.

// 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;
    }
}

Then in the sender view model you use the event aggregator to publish the event. Note, that you need to create or inject an instance eventAggregator of the event aggregator.

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

In the receiving view model you need to subscribe to the event eg in the constructor.

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

Create a method OnTankChanged to handle the event when it is received.

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

You can read about it in detail here . For an example in Caliburn Micro refer to this site . Although these mechanisms are built into the corresponding frameworks, you can also use them isolated in your project without migrating the whole application. However, there are also other implementations out there, but these frameworks are a good starting point, as they have a comprehensive documentation on that topic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM