MVVM - what is the ideal way for usercontrols to talk to each other

后端 未结 9 1285
失恋的感觉
失恋的感觉 2020-12-08 05:24

I have a a user control which contains several other user controls. I am using MVVM. Each user control has a corresponding VM. How do these user controls send information to

相关标签:
9条回答
  • 2020-12-08 06:03

    Typically, it's best to try to reduce the amount of communication between parts, as each time two user controls "talk" to each other, you're introducing a dependency between them.

    That being said, there are a couple of things to consider:

    • UserControls can always "talk" to their containing control via exposing properties and using DataBinding. This is very nice, since it preserves the MVVM style in all aspects.
    • The containing control can use properties to "link" two properties on two user controls together, again, preserving clean boundaries

    If you do need to have more explicit communication, there are two main approachs.

    1. Implement a service common to both elements, and use Dependency Injection to provide the implementation at runtime. This lets the controls talk to the service, which can in turn, keep the controls synchronized, but also keeps the dependency to a minimum.
    2. Use some form of messaging to pass messages between controls. Many MVVM frameworks take this approach, as it decouples sending the message from receiving the message, again, keeping the dependencies to a minimum.
    0 讨论(0)
  • 2020-12-08 06:03

    If you're using strict MVVM, then the user-control is a View and should only "talk", or rather, bind, to its ViewModel. Since your ViewModels most likely already implement INotifyPropertyChanged, as long as they have a reference to each other, they can use the PropertyChanged events to be notified when properties change, or they can call methods (better if it's through an interface) to communicate with each other.

    0 讨论(0)
  • 2020-12-08 06:04

    Your conceptual problem is here:

    Each user control has a corresponding VM.

    Having a separate ViewModel for every view pretty much defeats the concept of a ViewModel. ViewModels should not be one-to-one with views, otherwise they are nothing but glorified code-behind.

    A ViewModel captures the concept of "current user interface state" -- such as what page you are on and whether or not you are editing -- as opposed to "current data values'.

    To really reap the benefits of M-V-VM, determine the number of ViewModel classes used based on distinct items that need state. For example, if you have a list of items each of which can be displayed in 3 states, you need one VM per item. Contrarily, if you have three views all of which display data in 3 different ways depending on a common setting, the common setting should be captured in a single VM.

    Once you have strucutred your ViewModels to reflect the requirements of the task at hand you generally find there is no need nor desire to communicate state between views. If there is such a need, the best thing to do is to re-evaluate your ViewModel design to see if a shared ViewModel could benefit from a small amount of additional state information.

    There will be times when the complexity of the application dictates the use of several ViewModels for the same model object. In this case the ViewModels can keep references to a common state object.

    0 讨论(0)
  • 2020-12-08 06:10

    I think the best solution would be using Publisher/Subscriber pattern. Each control registers some events and attaches delegetes to events exposed by other controls.

    In order to expose events and attach to them you would need to use some kind of Mediator/EventBroker service. I found a good example here

    0 讨论(0)
  • 2020-12-08 06:12

    The best way to do this in my opinion is via Commanding (Routed Commands / RelayCommand, etc).

    I want to avoid writing any code in the xaml code behind.

    While this is a laudable goal, you have to apply a bit of practicality to this, it shouldn't be applied 100% as a "thou shalt not" type of rule.

    0 讨论(0)
  • 2020-12-08 06:16

    You can share some View Model objects between controls as well as Commands...

    For example, you have some main control, which contains two other controls. And you have some filtering functionality in the main control, but you want to allow user to set some part of the filter in the first sub-control (like "Full filter") and some part of the filter in another (like "Quick filter"). Also you want to be able to start filtering from any of sub-controls. Then you could use code like this:

    public class MainControlViewModel : ObservableObject
    {
        public FirstControlViewModel firstControlViewModel;
        public SecondControlViewModel firstControlViewModel;
    
        public ICommand FilterCommand;
        public FilterSettings FilterSettings;
    
        public MainControlViewModel()
        {
            //...
    
            this.firstControlViewModel = new FirstControlViewModel(this.FilterSettings, this.FilterCommand);
            this.secondControlViewModel = new SecondControlViewModel(this.FilterSettings, this.FilterCommand);
        }
    }
    
    public class FirstControlViewModel : ObservableObject
    {
        //...
    }
    
    public class SecondControlViewModel : ObservableObject
    {
        //...
    }
    

    In the main control XAML you will bind sub-controls DataContext to the appropriate View Models. Whenever a sub-control changes filter setting or executes a command other sub-control will be notified.

    0 讨论(0)
提交回复
热议问题