WPF MVVM: привязка другой ViewModel к каждому элементу TabItem?

У меня есть главное окно с элементом управления вкладкой, содержащим 2 tabItem s:

Main Window

В настоящее время у меня есть 1 ViewModel, который обслуживает Tab1 и Tab2. Этот ViewModel становится немного раздутым с размытым SOC. Я хочу разделить логику на 2 режима просмотра: ViewModel 1 и ViewModel2. Я понимаю, что вы можете установить главное окно DataContext на базовую модель ViewModel, которая содержит коллекцию ViewModels, а затем вы можете утверждать каждый TabItem в другой ViewModel.

Пример, который я видел в этих базовых ViewModels, выставляет ObservableCOllection следующим образом:

private ObservableCollection<ViewModel1> _viewModelCollection
Public Observable Collection<ViewModel1> ViewModelCollection
{
   get { return _viewModelCollection; }
   set
     {
        _viewModelCollection = value;
        OnPropertyChanged("ViewModelCollection");
     }
}

public BaseViewModel()
{
  ViewModelCollection = new ObservableCollection<ViewModel1>();
  ViewModelCollection.Add(new ViewModel1(Tab1);
  ViewModelCollection.Add(new ViewModel1(Tab2);
}

Но как мне назначить другой ViewModel для каждого TabItem? Я бы хотел, чтобы Tab1 = ViewModel1 и Tab2 = ViewModel2?

Ответы

Ответ 1

Вы действительно можете добавить модели представления для своих вкладок в основную модель представления. Затем вы можете привязать к модели просмотра детей в XAML для своих вкладок.

Скажите, что у вас есть три режима просмотра: MainViewModel, Tab1ViewModel и Tab2ViewModel. На вашем MainViewModel вы сохраняете коллекцию моделей отображения вкладок:

class MainViewModel
{
    ObservableCollection<object> _children;

    public MainViewModel()
    {
        _children = new ObservableCollection<object>();
        _children.Add(new Tab1ViewModel());
        _children.Add(new Tab2ViewModel());
    }

    public ObservableCollection<object> Children { get { return _children; } }
}

После установки DataContext вашего основного окна на ваш MainViewModel вы можете привязать DataContext к вашим вкладкам, указав свойство Children:

<TabControl>
    <TabItem DataContext="{Binding Children[0]}" x:Name="Tab1" Header="Tab1" >
      <!-- Tab content -->
    </TabItem>
    <TabItem DataContext="{Binding Children[1]}" x:Name="Tab2" Header="Tab2" >
      <!-- Tab content -->
    </TabItem>
</TabControl>

Ответ 2

Я использую структуру, такую ​​как Prism, которая позволяет вам определять области и использовать RegionManager. Затем вы можете определить ContentControl как "ui" для TabItem

Затем вы можете использовать RegionManager.RequestNavigate для заполнения именованной области с определенным представлением (и наши представления импортируют viewmodel и устанавливают их datacontext).

Ответ 3

class MainViewModel
{
    ObservableCollection<object> _children;

    public MainViewModel()
    {
        _children = new ObservableCollection<object>();
        _children.Add(new Tab1ViewModel());
        _children.Add(new Tab2ViewModel());
    }

    public ObservableCollection<object> Children { get { return _children; } }
}

Теперь в XAML привяжите Children к ItemsSource. Он будет генерировать каждую вкладку для каждой модели, которую мы добавили в наблюдаемую коллекцию

    <TabControl ItemsSource="{Binding Children}"/>

Ответ 4

Для людей, которые находят эту страницу с тем же вопросом, я нашел видео на YouTube: WPF MVVM - Работа с элементами управления вкладками и содержимым вкладок, разработанная компанией DCOM Engineering, LLC.

Это дает очень хорошее объяснение того, "как привязать разные ViewModel к каждому TabItem ", шаг за шагом, с загружаемым кодом.

"Узнайте, как эффективно создавать, открывать и закрывать вкладки, используя шаблон MVVM с WPF. Облегчает модульное тестирование".