#.net #wpf #mvvm
#.net #wpf #mvvm
Вопрос:
Я не хочу помещать все это в одну ViewModel, я хочу иметь одну ViewModel на TabItem.
Я создал MainViewModel для окна, содержащего TabControl, где у меня есть это свойство currentViewModel, указывающее на значение по умолчанию в конструкторе MainViewModel
public MainViewModel()
{
currentViewModel = "viewModel1";
}
Когда пользователь нажимает на другую TabItem, выполняется
currentViewModel = "viewModel2";
и, конечно, средство доступа set имеет метод OnPropertyChanged
public String currentViewModel
{
get { return _currentViewModel; }
set
{
_currentViewModel = value;
OnPropertyChanged("currentViewModel");
}
}
Еще две ViewModels (ViewModel1, viewModel2), каждая из которых определяет функциональность одной из TabItems, между которыми я хочу переключаться.
Теперь в моем Main.xaml я хочу привязать мой DataContext сначала к MainViewModel, а затем к свойству currentViewModel. чтобы всякий раз, когда пользователь нажимает на TabItem, свойство currentViewModel обновлялось, а DataContext указывал на соответствующую viewmodel.
Комментарии:
1. Используя строку для установки viewmodels? Фу, я не думаю, что это необходимо. Также обычно вокруг этих двух строк в установщике должен быть
if (_fieldOfProperty != value)
блок.
Ответ №1:
Я думаю, что хорошим подходом было бы создание пользовательских элементов управления для каждого элемента tab. Затем в каждом usercontrol вы будете ссылаться на правильное пространство имен ViewModel для привязки.
В вашем MainWindow будет tabcontrol, и каждый tabitem внутри tabcontrol будет привязан к определенному usercontrol (который обрабатывается как отдельное представление).
mainwindow_View.xaml будет привязан к mainwindow_ViewModel.cs tabItem1_View.xaml будет привязан к ViewModel1.cs tabItem2_View.xaml будет привязан к ViewModel2.cs
Если вам нужен пример кода, дайте мне знать.
Комментарии:
1. Не могли бы вы, пожалуйста, предоставить мне какой-либо пример кода. Заранее спасибо.
Ответ №2:
Я сомневаюсь, что это то, что вы действительно хотите сделать, если у вас разные ViewModels, вы все равно можете привязать свой элемент управления к коллекции этих ViewModels и шаблонировать их по мере необходимости.
Вам просто нужно создать разные DataTemplates на разных уровнях, вот пример (который напрямую использует models, но сейчас это не должно иметь значения):
<TabControl>
<TabControl.ItemsSource>
<!-- This is just sample data, normally you would bind this to an
ObservableCollection<ViewModelBase> or something similar -->
<x:Array Type="{x:Type sys:Object}">
<local:Employee Name="John" Occupation="Programmer"/>
<local:Employee Name="Steve" Occupation="Coffee Getter"/>
<local:Machine Manufacturer="iCorp" Model="iMachine"/>
<local:Machine Manufacturer="iCorp" Model="iMachine G2"/>
<local:Employee Name="Marc" Occupation="GUI Designer"/>
</x:Array>
</TabControl.ItemsSource>
<TabControl.Resources>
<!-- These datatemplates define the tab-header appearance, by placing them
in the TabControl.Resources and setting the DataType they get applied
automatically, just make one light-weight template for each ViewModel -->
<DataTemplate DataType="{x:Type local:Employee}">
<TextBlock>
<Run Text="{Binding Name}"/>
<Run Text="("/>
<Run Text="{Binding Occupation}"/>
<Run Text=")"/>
</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Machine}">
<TextBlock>
<Run Text="{Binding Manufacturer}"/>
<Run Text=" - "/>
<Run Text="{Binding Model}"/>
</TextBlock>
</DataTemplate>
<ContentControl x:Key="MainContent" Content="{Binding}">
<ContentControl.Resources>
<!-- This represents the content of the TabItems, you probably
do not need to create DataTemplates but since you could
use a View of the ViewModels instead -->
<DataTemplate DataType="{x:Type local:Employee}">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Occupation}"/>
<TextBlock Text="{Binding Id}"/>
<TextBlock Text="{Binding IsActive}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Machine}">
<StackPanel>
<TextBlock Text="{Binding Manufacturer}"/>
<TextBlock Text="{Binding Model}"/>
<TextBlock Text="{Binding VintageYear}"/>
<TextBlock Text="{Binding Price}"/>
</StackPanel>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</TabControl.Resources>
<TabControl.ContentTemplate> <!-- Setting the content to the resource -->
<DataTemplate>
<Border>
<StaticResource ResourceKey="MainContent"/>
</Border>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Я мог бы попытаться реализовать специфику для MVVM, но, надеюсь, это уже дает представление о том, как к этому можно подойти.
Возможно, вам захочется настроить селектор шаблонов ( TabControl.ContentTemplateSelector
), чтобы получить правильные представления для ваших ViewModels.