数据模板

数据模板

介绍

数据模板类似于控件模板的概念。他给你非常灵活和强有力的比如在ListBox、ComboBox或ListView中替换数据项的可视化外观的解决方案。在我看来,这是WPF成功的关键之一。
如果你没有详细指定一个数据模板,WPF使用仅有一个TextBlock的默认模板。如果你绑定复杂的对象到空间上,仅仅调用它的ToString函数。数据模板内,DataContext被设置为数据对象。所以你可以轻松地绑定数据上下文来展示你的数据对象各种各样的成员。

数据模板实践,构建简单的属性网格

鉴于WinForms展示复杂对象在ListBox中是非常困难的,而WPF是非常轻松的。下列例子展示了DependencyPropertyInfo实例列表绑定到ListBox。没有数据模板我们只是看到在对象上调用ToString函数的结果。在数据模板内,我们看到属性名称和允许编辑值得TextBox。

!(图片)[http://wpftutorial.net/images/with_without_datatemplates.png]

<!-- Without DataTemplate -->
<ListBox ItemSource="{Binding}"/>

<!-- With DataTemplate -->
<ListBox ItemSource="{Binding}" Grid.IsSharedSizeScope="True" HorizontalContentAlignment="Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Margin="4">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" ShareSizeGroup="Key">
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Name}" FontWeight="Bold">
                <TextBox Grid.Column="1" Text="{Binding Value}">
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

如何使用数据模板选择器依赖于数据切换模板

我们得属性网格看起来离着完美还很远,但是如果我们可以依赖于属性的类型切换编辑它将会变得非常有用。
最简单的方式是使用数据模板选择器。数据模板选择器具有一个方法可以被重写:SelectTemplate(object item, DependencyObject container)。在这个方法中我们基于已提供的item决定选择哪个数据模板。

public class PropertyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultDataTemplate{ get; set; }
    public DataTemplate BooleanDataTemplate{ get; set; }
    public DataTemplate EnumDataTemplate{ get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        DependencyObjectInfo dpi = item as DependencyPropertyInfo;

        if(dip.PropertyType == typeof(bool))
        {
            return BooleanDataTemplate;
        }
        if(dip.PropertyType.IsEnum)
        {
            return EnumDataTemplate;
        }

        return DefaultDataTemplate;
    }
}
<Window x:Class="DataTemplates.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:DataTemplates"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <Window.Resources>
        <!-- Default DataTemplate -->
        <DateTemplate x:Key="DefaultDataTemplate">
            内容...
        </DataTemplate>

        <!-- DataTemplate for Boolean -->
        <DateTemplate x:Key="BooleanDataTemplate">
            内容...
        </DataTemplate>

        <!-- DataTemplate for Enums -->
        <DateTemplate x:Key="EnumDataTemplate">
            内容...
        </DataTemplate>

        <!-- DataTemplate Selector -->
        <l:PopertyDataTemplateSelector x:Key="templateSelector"
        DefaultDataTemplate="{StaticResource DefaultDataTemplate}"
        BooleanDataTemplate="{StaticResource BooleanDataTemplate}"
        EnumDataTemplate="{StaticResource EnumDataTemplate}"
        >
    </Window.Resources>
    <Grid>
        <ListBox ItemSource="{Binding}" Grid.IsSharedSizeScope="True" HorizontalContentAlignment="Stretch"ItemTemplateSelector="{StaticResource templateSelector}">
    </Grid>
</Window>

如何对数据模板中的isSelected起作用

如果当ListBox项被选中时,你想要改变它的外观,你必须绑定ListBox项的IsSelected属性。但是有一个小技巧,你必须使用查找祖先的相对资源向上导航可视化树知道你到达ListBox项

<DataTemplate x:Key="DefaultDataTemplate">
    <Border x:Name="border" Height="50">
        ...
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType={x:TypeListItem}},Path=IsSelected}" Value="True">
            <Setter TargetName="border" Property="Height" Value="100">
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
posted @ 2023-09-01 09:38  Juston007  阅读(66)  评论(0)    收藏  举报