WPF如何设置基于类型的数据模板

本文关键字:类型 数据 何设置 设置 WPF 于类型 | 更新日期: 2023-09-27 18:18:01

我在我的XAML中有以下代码,其中显示TabControl和模板,以显示标题,内容和关闭按钮以关闭选项卡。但我希望内容根据选项卡的类型有所不同。即视图模型的类型。现在它是硬编码到一个特定的视图。我之前在数据模板中使用了Data Type属性。但我不确定如何使用它与模板选择器的组合。

<Window.Resources>
    <DataTemplate x:Key="ClosableTabItemTemplate">
        <DockPanel Width="120">   
            <Button 
                Command="{Binding ElementName=MainTabControl, Path=DataContext.RemoveTabCommand}"
                CommandParameter="{Binding Path=DealName}"
                Content="x"
                Cursor="Hand"
                DockPanel.Dock="Right"
                Focusable="False"
                FontFamily="Courier" 
                FontSize="9"
                FontWeight="Bold"                      
                Padding="0"
                VerticalContentAlignment="Bottom"
                Width="16" Height="16" 
            />
            <ContentControl
                Content="{Binding Path=Header}"                    
                VerticalAlignment="Center">
                <ContentControl.Style>
                    <Style>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=Header}" Value="New Deal">
                                <Setter Property="ContentControl.Foreground" Value="Blue"></Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>                
        </DockPanel>
    </DataTemplate>
    <DataTemplate x:Key="newTabButtonContentTemplate">
        <Grid/>
    </DataTemplate>
    <DataTemplate x:Key="newTabButtonHeaderTemplate">
        <Button Content="+" Width="20"  Height="20" Command="{Binding ElementName=MainTabControl, Path=DataContext.NewTabCommand}"/>
    </DataTemplate>
    <DataTemplate x:Key="itemContentTemplate">
        <v:DealView/>
    </DataTemplate>
    <v:TemplateSelector x:Key="headerTemplateSelector"
                       NewButtonTemplate="{StaticResource newTabButtonHeaderTemplate}"
                       ItemTemplate="{StaticResource ClosableTabItemTemplate}"/>
    <v:TemplateSelector x:Key="contentTemplateSelector"
                        NewButtonTemplate="{StaticResource newTabButtonContentTemplate}"
                        ItemTemplate="{StaticResource itemContentTemplate}"/>
</Window.Resources>
<Window.DataContext>
    <vm:MainViewModel />
</Window.DataContext>
<Grid>
    <DockPanel>
        <TabControl DockPanel.Dock="Bottom"  x:Name="MainTabControl"  Margin="2" ItemsSource="{Binding Tabs}" 
                               IsSynchronizedWithCurrentItem="True"                                 
                               ItemTemplateSelector="{StaticResource headerTemplateSelector}"
                               ContentTemplateSelector="{StaticResource contentTemplateSelector}">
            <TabControl.Resources>
                <Style TargetType="{x:Type TabPanel}">
                    <Setter Property="Background" Value="AliceBlue"/>
                </Style>                   
            </TabControl.Resources>
        </TabControl>
    </DockPanel>
</Grid>

我的TemplateSelector课程如下:

public class TemplateSelector : DataTemplateSelector
{
    public DataTemplate ItemTemplate { get; set; }
    public DataTemplate NewButtonTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item == CollectionView.NewItemPlaceholder)
        {
            return NewButtonTemplate;
        }
        else
        {
            return ItemTemplate;
        }
    }
}

My tabs是ViewModels的集合:

public ObservableCollection<ViewModelBase> Tabs
{
    get
    {
        if (tabs == null)
        {
            tabs = new ObservableCollection<ViewModelBase>();
            var itemsView = (IEditableCollectionView)CollectionViewSource.GetDefaultView(tabs);
            itemsView.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtEnd;
         }
        return tabs;
     }
 }

所以我想在ItemContentTemplate数据模板中这样设置:

<DataTemplate x:Key="itemContentTemplate">
    when type is DealViewModel use  <v:DealView/>
    when type is DealSummaryViewModel use <v:DealSummaryView/>
    etc
</DataTemplate>

WPF如何设置基于类型的数据模板

我之前在数据模板中使用了Data Type属性。但我不是知道如何将它与模板选择器结合使用。

如果你只是回落到基础,如:

return base.SelectTemplate(item, container);

…您应该得到默认行为,即选择具有匹配DataType的模板。这就足够了吗?(实际上,您可以只返回null,因为这就是它所做的。)

另一个选项是从选择器访问资源键:

return ((FrameworkElement)container).FindResource(resourceKey) as DataTemplate;

,其中resourceKey是基于项计算的,并且具有该键的模板定义在比容器更高的树位置