问题
Control different DataContext in WPF
As I can deploy multiple DataContext in different tabs and control which is the current DataContext

I'm using Mvvm Light WPF4 i have the different ViewModels, View but i dont know how to handle multiples DataContext and control the current DataContext for change on tab switch
Edit:
I've got an approach to the solution as follows:
- Create a ViewModel for the MainView
- The tabcontrol source is a ObservableCollection
- Each TabItem has its own DataContext
- The menu has the DataContext like this:
DataContext="{Binding Path=CurrentTab.DataContext}"
where CurrentTab change when add new TabItem in the ViewModel
i have the following problems:
- how do I connect the ViewModel from the TabControl when you change the tab?
Solution: the problem is that Mvvm Light uses a ViewModelLocator for Binding ViewModel in static way, this is the problem when i add tab in C# the ViewModelLocator dont works, in other way i need load manually the ViewModel for each tab like this:
// in MainModelView.cs
public RelayCommand MyCommand { get; set; }
private void RegisterCommand()
{
MyCommand = new RelayCommand(() =>
{
AddTab("Tab Header", new TabViewModel(), new TabContentControl());
});
}
private void AddTab(string header, object context, ContentControl content)
{
TabItem = null;
foreach(TabItem tab in TabItemList)
{
if(tab.Header.Equals(header);
{
tabItem = tab;
}
}
if(null == tabItem)
{
tabItem = new TabItem();
tabItem.Header = header;
tabItem.Content = content;
tabItem.DataContext = context;
TabItemList.Add(tabItem);
}
CurrentTabIndex = TabItemList.IndexOf(tabItem);
}
2.the DataContext dont update in the menu, my code is wrong?
Solution: the previous point solve this too and only with the follow code solved:
// in RegisterCommands()
ChangeTabCommand = new RelayCommand<TabItem>(tab =>
{
if (null == tab) return;
CurrentTabContext = tab.DataContext;
}
in MainWindow.xml:
<!-- MainWindow.xaml -->
<Button Content="NewTab" Command="{Binding Path=MyCommand }" />
<TabControl
Margin="5 5 5 0"
Grid.Row="1"
ItemsSource="{Binding Path=TabItemList}"
SelectedIndex="{Binding Path=CurrentTabItemIndex}"
x:Name="Workspace">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand
Command="{Binding ChangeTabCommand }"
CommandParameter="{Binding SelectedItem, ElementName=Workspace}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TabControl>
Edit 2:
- How to avoid modifying the view in the ViewModel and send the necessary parameters from the same view (ContenControl, Header, Context)
回答1:
I would create a ViewModelContainer that has a property for each of your view models (e.g. MainViewModel, Tab1ViewModel, Tab2ViewModel). The you can bind ViewModelContainer as DataContext of the Window and bind each TabItem DataContext to the right VM object in this way DataContext="{Binding Tab1ViewModel}"
No suggestion for problem 2.
Update
Your code does not follow MVVM at 100%. Your command edit the view and viewmodel. If you want to be painstaking the command must interact only with viewmodel. The viewmodel then will signal (through an ObservableCollection or an INotifyPropertyChanged interface) the view that will reply by adding a new tabItem. I suppose that the View part can be managed 100% with XAML using ItemTemplate to define how the panels should appear.
来源:https://stackoverflow.com/questions/10404313/control-different-datacontext