I have a main VM which stores 2 UserControl and VM-ки to them. UserControl is UserControl due to the CurrentUserControl property that binds to the view. How correctly to store UserControl inside ViewModel and how best to do it from the MVVM architecture?

Also, to change one UserControl to another, I send a link to the main VM to each VM-ку and it changes them through this link. I also doubt the correctness of this decision.

 public class MainVm : VmBase { public MainVm() { LoginAndRegisterVm = new LoginAndRegisterVm(this); EnterRegistrationKeyVm = new EnterRegistrationKeyVm(this); EnterRegistrationKeyUserControl = new EnterRegistrationKey(); EnterRegistrationKeyUserControl.DataContext = EnterRegistrationKeyVm; LoginUserControl.DataContext = LoginAndRegisterVm; CurrentUserControl = LoginUserControl; } public LoginAndRegisterVm LoginAndRegisterVm { get; set; } public EnterRegistrationKeyVm EnterRegistrationKeyVm { get; set; } public UserControl LoginUserControl { get; set; } = new LoginPage(); public UserControl EnterRegistrationKeyUserControl { get; set; } private UserControl _currentUserControl; public UserControl CurrentUserControl { get { return _currentUserControl; } set { _currentUserControl = value; NotifyPropertyChanged(); } } } 

Part of Xaml :

 <UserControl Grid.Row="1" Content="{Binding CurrentUserControl}" /> 

    1 answer 1

    In terms of MVVM, it is not. The VM does not need to know and have an idea about View, about whether the given VM is currently displayed on the screen, and if so, how and in how many places.


    I think the correct pattern for your case is:

    1. You get two nested VMs: for your case, it seems, LoginAndRegisterVm and EnterRegistrationKeyVm .
    2. MainVm CurrentPart type VmBase . LoginAndRegisterVm or EnterRegistrationKeyVm it as you need.
    3. In View, write bindings:

       <DataTemplate DataType="{x:Type vm:EnterRegistrationKeyVm}"> <!-- здесь контент для отображения EnterRegistrationKeyVm, например просто: --> <view:EnterRegistrationKeyUserControl/> </DataTemplate> <DataTemplate DataType="{x:Type vm:LoginAndRegisterVm}"> <view:LoginUserControl/> </DataTemplate> 
    4. Basically, you just write XAML

       <ContentPresenter Content="{Binding CurrentPart}"/> 

    The binding of the DataContext to happen automatically.


    The question of the correctness of changing one VM object by another is not regulated by MVVM. Apply the pattern that you think is more correct.

    • In order to make a multipage application, you need to replace one UserControl with another. Where then should UserControl be stored if not in the VM and who should manage their shift? - Lightness
    • @Lightness: Added an answer. UserControl must be uniquely in View. - VladD
    • VmBase simply implements INPC . If you write a VM it, can the control be able to see the properties that are sitting in it? Or will this happen thanks to DataType="{x:Type vm:LoginAndRegisterVm}" ? - Lightness
    • @Lightness: Yes, WPF looks at a runtime type. How do you think Binding works to the DataContext properties, because the DataContext property is of type object ? - VladD
    • Indeed, did not think about it. Thanks for the answer! - Lightness