WPF MVVM:设置选项卡视图的 DataContext

Jai*_*Jai 0 wpf datacontext tabcontrol datatemplate mvvm

我遇到了一种奇怪的绑定行为,这里描述。我做了很多故障排除,我得出的结论是,最可能的问题在于我如何设置DataContext每个选项卡的视图。

我有一个TabControlItemsSource绑定到列表ViewModels

MainView:
<TabControl ItemsSource="{Binding TabList}">
    <TabControl.Resources>
        <DataTemplate DataType="{x:Type vm:Tab1ViewModel}">
            <v:Tab1 />
        </DataTemplate>
    </TabControl.Resources>
...
</TabControl>

MainViewModel:
public ObservableCollection<TabViewModelBase> TabList { get; set; }
public MainViewModel()
{
    this.TabList = new ObservableCollection<TabViewModelBase>();

    // Tab1ViewModel is derived from TabViewModelBase
    this.TabList.Add(new Tab1ViewModel()); 
}
Run Code Online (Sandbox Code Playgroud)

所以,现在MainViewModel有一个列表TabViewModelBase,我相信这是正确的 MVVM 方法。视图 ( Tab1)TabViewModelBase是使用 定义的DataTemplate

这就是问题所在:

Tab1:
<UserControl.Resources>
    <vm:Tab1ViewModel x:Key="VM" />
</UserControl.Resources>
<UserControl.DataContext>
    <StaticResourceExtension ResourceKey="VM" />
</UserControl.DataContext>
Run Code Online (Sandbox Code Playgroud)

我想大多数人也会这样做,但是......这种方法有一些非常错误的地方

在 中MainViewModel,我手动实例化了一个Tab1ViewModel. 在 中MainView,我曾经DataTemplate告诉 ViewTab1在看到 a 时使用a Tab1ViewModel。这意味着MainView将实例化一个Tab1类对象。

现在,Tab1需要它DataContext和自己的绑定Tab1ViewModel,所以我们使用StaticResource添加一个Tab1ViewModel,除了这是一个全新的实例!

我需要将DataContext返回设置为我在MainViewModel. 那么,我如何设置DataContextofTab1DataTemplate

Kyl*_*Ren 5

您不必vm:Tab1ViewModel在 XAML 中指定新实例。您也不需要DataContext明确定义。列表的每个项目是ViewModel每当一个类型ViewModel与你所定义的类型相匹配DataTemplate的微粒view会被渲染和相同DataContextViewModel。例如,如果列表有两个对象,如下所示:

public ObservableCollection<TabViewModelBase> TabList { get; set; }
public MainViewModel()
{
    this.TabList = new ObservableCollection<TabViewModelBase>();
    this.TabList.Add(new Tab1ViewModel1()); 
    this.TabList.Add(new Tab1ViewModel2()); 
}
Run Code Online (Sandbox Code Playgroud)

DataTemplate是:

<TabControl ItemsSource="{Binding TabList}">
<TabControl.Resources>
    <DataTemplate DataType="{x:Type vm:Tab1ViewModel}">
        <v:Tab1 />
    </DataTemplate>
   <DataTemplate DataType="{x:Type vm:Tab1ViewModel2}">
        <v:Tab2 />
    </DataTemplate>
</TabControl.Resources>
Run Code Online (Sandbox Code Playgroud)

...

然后两个选项卡将呈现Tab1Tab2(原因列表中有2项)。Tab1将有Tab1ViewModel1作为DataContext,并与Tab2将有 Tab1ViewModel2作为DataContext。您无需DataContext 明确指定。