WPF MVVM:设置选项卡视图的DataContext [英] WPF MVVM: Setting DataContext of Tab Views

查看:476
本文介绍了WPF MVVM:设置选项卡视图的DataContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在此处中描述了一种奇怪的绑定行为.我进行了大量的故障排除,得出的结论是,最可能的问题在于如何设置每个选项卡视图的DataContext.

I have experienced a weird binding behavior that is described here. I did a lot of troubleshooting and I came to the conclusion that the most likely problem lies at how I set the DataContext of each of the tab's view.

我有一个TabControl,其ItemsSource绑定到ViewModels的列表.

I have a TabControl whose ItemsSource is bound to a list of 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()); 
}

因此,现在MainViewModel有一个TabViewModelBase列表,我相信这是执行此操作的正确MVVM方法. TabViewModelBase的视图(Tab1)是使用DataTemplate定义的.

So, now the MainViewModel has a list of TabViewModelBase, which I believe is the correct MVVM way to do this. The view (Tab1) for TabViewModelBase is defined using DataTemplate.

这是问题所在:

Tab1:
<UserControl.Resources>
    <vm:Tab1ViewModel x:Key="VM" />
</UserControl.Resources>
<UserControl.DataContext>
    <StaticResourceExtension ResourceKey="VM" />
</UserControl.DataContext>

我认为大多数人也会这样做,但是... 这种方法有些严重错误

I think most people would do this as well, but... There is something terribly wrong with this approach!

MainViewModel中,我手动实例化了Tab1ViewModel.在MainView中,我使用DataTemplate告诉视图在看到Tab1ViewModel时使用Tab1.这意味着MainView将实例化Tab1类的对象.

In MainViewModel, I have manually instantiated a Tab1ViewModel. In MainView, I used DataTemplate to tell the View to use a Tab1 whenever it sees a Tab1ViewModel. That means MainView would instantiate an object of Tab1 class.

现在,Tab1需要其DataContext与自己的Tab1ViewModel进行绑定,因此我们使用StaticResource添加一个Tab1ViewModel,只是这是一个全新的实例!

Now, Tab1 needs its DataContext to do binding with its own Tab1ViewModel, so we use StaticResource to add one Tab1ViewModel, except that this is a brand new instance!

我需要将DataContext设置回在MainViewModel中实例化的原始位置.那么,如何在DataTemplate中设置Tab1DataContext?

I need to set the DataContext back to the original one that I instantiated in MainViewModel. So, how do I set the DataContext of Tab1 within DataTemplate?

推荐答案

您不必在XAML中指定vm:Tab1ViewModel新实例.您也不需要显式定义DataContext.只要ViewModel的类型与您在DataTemplate中定义的类型相匹配的粒子view都将呈现且与ViewModel相同的DataContext,则列表中的每个项目都是ViewModel.例如,如果list具有以下两个对象:

You don't have to specify vm:Tab1ViewModel new instance in your XAML. Neither do you need to define the DataContext explicitly. Every item of your list is a ViewModel whenever the type of a ViewModel matched with the type you have defined in DataTemplate a particulate view will be rendered and with the same DataContext as ViewModel. For example if list has two objects like below:

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

而您的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>

...

然后两个选项卡将呈现Tab1& Tab2(原因列表包含2个项目). Tab1将具有Tab1ViewModel1作为DataContext,而Tab2将具有 Tab1ViewModel2作为DataContext.您无需指定DataContext

then Two tabs will be renders Tab1 & Tab2 (cause list has 2 items). Tab1 will have Tab1ViewModel1as DataContext and and Tab2 will have Tab1ViewModel2 as DataContext. You need not specify DataContext explicitly.

这篇关于WPF MVVM:设置选项卡视图的DataContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆