Hello. I'm currently learning WPF and MVVM. Recently, I have a question that I have not been able to find the answer. The essence of the problem is as follows:

I have a window in which the ComboBox is present. In it, the user selects the operation he needs. ComboBox values ​​are enum Operaton elements that are bound by a binding to an ItemsSource. There is also a ListBox displaying user-selected objects and several Button. Depending on the operations selected in the ComboBox, the objects displayed in the ListBox and the commands executed by some buttons change. At the same time, the View remains the same.

I created my ViewModel for each selected operation and placed them as public properties in the main MainViewModel. For the main window, set DataContext = MainViewModel. For ListBox and buttons that change the behavior of DataContext = MainViewModel.FirstOperationViewModel. But how to change this DataContext when the operation selected in the ComboBox changes? I come up with two options:

  1. Modify with an event handler in code behind, violating the idea of ​​MVVM.
  2. Make the binding DataContext of the controls I need and the SelectedItem of my ComboBox using the ValueConverter. This option seems to me quite doubtful.

In this regard, I have questions:

  1. How to correctly implement this behavior in the framework of MVVM?
  2. Does it make sense in this case to stick to MVVM? Because In some cases, as I understand it, a departure from this model makes sense.
  3. Maybe use some other approach to solve this problem? If so, then at least briefly describe it.

Thank.

  • If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky ♦

1 answer 1

I would do this.

What you choose in a combo box is not enum , it is an operation with meaning. Therefore, the combobox must be tied not to enum (it is not needed at all), but to approximately the following data structure:

 class Operation { public string Name { get; private set; } // имя public ICommand AddCommand { get; private set; } // команда для кнопки Add public ICommand DeleteCommand { get; private set; } // команда для кнопки Delete } 

The content of the class will not change after the constructor, so INPC can not be implemented.

Then, in the MainViewModel start

 public IEnumerable<Operation> Operations { get; private set; } public Operation CurrentOperation { get; set; } // <-- Ρ‚ΡƒΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚Π΅ INPC 

and tie combobox like

 <ComboBox ItemsSource="{Binding Operations}" DisplayMemberPath="Name" SelectedItem="{Binding CurrentOperation, Mode=TwoWay}"/> 

Now the buttons can be tied to the current operation:

 <Button Content="Add" Command="{Binding CurrentOperation.AddCommand}"/> <Button Content="Delete" Command="{Binding CurrentOperation.DeleteCommand}"/> 

What to do with the list (you write that it depends on the selected operation) depends on how it depends. Perhaps in each operation you need your own list, or your own filter for the list .


Yes, in some cases it makes sense to deviate from strict MVVM. But your case is not so complicated, here a retreat from MVVM should not be necessary.

  • Thank you for the comprehensive answer. - Evgeniy.Nik
  • @ Evgeniy.Nik: Please! - VladD