将一组相同类型的ViewModel绑定到MVVM / WPF中的TabControl的最佳方法

时间:2015-03-18 01:09:45

标签: c# wpf xaml

我在MVVM项目中有一个现有的ViewModel和View。实际上,此视图以特定的样式方式呈现项目集合。我将调用现有的ViewModel" CollectionPresenter"。

到目前为止,这在XAML中已经如下所示:

<Grid>
    <ns:CollectionPresenter />
</Grid>

现在,我希望动态收集这些&#34; CollectionPresenter&#34;视图模型在标签视图中理想地可用。

我的方法是定义这些&#34; CollectionPresenters&#34;的可观察集合,首先在构建父视图模型时创建它们。上面的XAML改为看起来像这样:

<TabControl ItemsSource="{TemplateBinding CollectionPresenters}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding CollectionPresenterTitle}">
        </DataTemplate>
    <TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
         ... this is where things get confusing
    </TabControl.ContentTemplate>
<TabControl>

您可以在上面看到我的问题是ContentTemplate。

当我加载它时,我得到一个标签控件,它有与我的可观察集合&#34; CollectionPresenter&#34;一样多的标签。对象。

但是,选项卡控件的内容始终为空。

这种方法是否正确 - 无论如何都有更好的方法吗?

编辑:添加一些额外的东西以使其更清晰

我已尝试过以下内容,但它不起作用。具有Tab控件的XAML(绑定到&#34; Things&#34;工作正常):

<TabControl ItemsSource="{TemplateBinding Things}">
    <TabControl.ItemTemplate>
        <DataTemplate DataType="{x:Type viewModels:Thing}">
                <TextBlock Text="{Binding ThingName}" Width="200" Background="Blue" Foreground="White"/>
        </DataTemplate>
    </TabControl.ItemTemplate>    
    <TabControl.ContentTemplate>
        <DataTemplate DataType="{x:Type viewModels:Thing}">
                <TextBlock Text="{Binding ThingName}" Width="500" Height="500" Background="Blue" Foreground="White"/>
        </DataTemplate>
    </TabControl.ContentTemplate>  
</TabControl>

&#34; Things&#34;的定义observable collection(在带有制表符控件的XAML的模板化父级(ParentObject)内):

public static readonly DependencyProperty ThingsProperty =
DependencyProperty.Register("Things", typeof(ObservableCollection<Thing>), typeof(ParentObject), new PropertyMetadata(null));

public ObservableCollection<Thing> Things
{
    get { return (ObservableCollection<Thing>)GetValue(ThingsProperty); }
    set { SetValue(ThingsProperty, value); }
}   

剥离版本的&#34; Thing&#34;查看模型:

public class Thing : ViewModelBase
{       
    public Thing()
    {
    }

    public void Initialise(ObservableCollection<Thing> things, string thingName)
    {            
        Things = things;
        ThingName = thingName;
    }

    public static readonly DependencyProperty ThingNameProperty =
    DependencyProperty.Register("ThingName", typeof(string), typeof(Thing), new PropertyMetadata(null));

    public string ThingName
    {
        get { return (string)GetValue(ThingNameProperty); }
        set { SetValue(ThingNameProperty, value); }
    }
}

1 个答案:

答案 0 :(得分:1)

查看我对WPF MVVM navigate views问题的回答,您可以看到:

<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
    <Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:PersonViewModel}">
    <Views:PersonView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:CompanyViewModel}">
    <Views:CompanyView />
</DataTemplate>

现在,无论我们在应用程序中使用其中一种类型的实例,这些DataTemplates都会告诉框架显示相关视图。

因此,您的解决方案是将一个DataTemplate硬编码到TabControl.ItemTemplate属性,而是将其留空。如果您使用多个DataTemplate s 提供x:Key值,那么当要在TabControl中呈现每个数据对象时,将隐式应用它们。


更新&gt;&gt;&gt;

使用这些DataTemplate会使TabControl看起来像这样:

<TabControl ItemsSource="{TemplateBinding Things}" />

我不确定你为什么要在那里使用TemplateBinding,因为你不需要定义任何新的模板来实现这个...因此,你应该是使用普通的旧Binding代替。

您需要做的另一件事是为集合中要以不同方式显示的每个项目使用不同的数据类型。您可以从Thing类派生自定义类,因此集合仍然可以是ObservableCollection<Thing>类型。