具有继承的ListView.Resources中的多个DataTemplates?

时间:2016-04-27 14:13:21

标签: c# xaml listview win-universal-app

所以我有一个包含多个DataTemplates的ListView,但我不确定这是否是正确的方法。我的XAML看起来像这样:

<ListView.Resources>
    <DataTemplate x:Key="ParentClass" x:DataType="local:ParentClass">
        <!-- The Template -->
    </DataTemplate>
    <DataTemplate x:Key="ChildClass" x:DataType="local:ChildClass">
        <!-- The Template -->
    </DataTemplate>
</ListView.Resources>

我的课程看起来像这样:

class ParentClass {}
class ChildClass: ParentClass {}

如果对象不是ParentClass,我怎么能确定这只会占用ChildClass模板?我需要将它们按特殊顺序排列吗?这对XAML来说是不可能的吗?我是否需要创建第二个&#34;虚拟&#34;儿童班完全避免这个问题?

1 个答案:

答案 0 :(得分:1)

简而言之,Windows Universal Apps不支持DataTemplate.DataType,并且无法在没有x:Key的情况下在资源字典中声明,因此Windows Universal Apps不支持数据类型的默认模板。 x:DataType附加属性不会执行DataType在WPF中执行的操作。

在Windows通用应用中,您可以将DataTemplate内联定义为ItemsControl.ItemTemplate或某些内容的值,或者您可以使用x:Key在资源字典中定义它。如果要选择模板,则必须编写DataTemplateSelector

因此,在您的问题代码中,您正在定义模板,但没有人使用它们。

这有点拖累。

WPF不同

这是我的原始答案,适用于WPF。 它不适用于Windows Universal Apps ,这是此问题的实际范围。它在标签中显示win-universal-app,但我没有阅读标签。因为它是正确的,并且可能是导致某人访问此页面的问题的答案,所以当我询问Meta是否应该删除它时,我会留在这里。

A DataTemplate without an x:Key property is applied to any object of the appropriate type。如果您有父类和子类的单独数据模板,它将使用最专业的数据模板。 MSDN notes that it's similar to Style.TargetType:想象一下,如果TargetType="{x:Type Button}"的默认样式没有自动覆盖ButtonBase的默认样式。 混乱会随之发生!我甚至找不到明确说明情况的文件。正如Brian Kernighan所说,“你的编译器是语言的最终权威”:这就是我在快速测试中表现的方式。

如果我颠倒DataTemplate定义的顺序,它的行为相同。如果我将ItemSubClass DataTemplate的定义移至Window.Resources,它的行为也相同。

XAML:

<ItemsControl
    ItemsSource="{Binding Items}"
    BorderBrush="Black"
    BorderThickness="1"
    Margin="4"
    >
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:ItemSubClass}">
            <Grid Background="Beige">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="1*" />
                    <ColumnDefinition Width="1*" />
                </Grid.ColumnDefinitions>
                <TextBlock 
                    Grid.Column="0" 
                    Text="{Binding Name, StringFormat=Name: {0}}" 
                    />
                <TextBlock 
                    Grid.Column="1" 
                    Text="{Binding Category, StringFormat=Category: {0}}" 
                    />
            </Grid>
        </DataTemplate>

        <DataTemplate DataType="{x:Type local:Item}">
            <TextBlock Text="{Binding Name, StringFormat=Name: {0}}" />
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

C#:

public class Item : INotifyPropertyChanged
{
    private string _name = "";
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] String propName = null)
    {
        PropertyChanged?.Invoke(this,
                    new PropertyChangedEventArgs(propName));
    }
}

public class ItemSubClass : Item
{
    #region Category Property
    private String _category = default(String);
    public String Category
    {
        get { return _category; }
        set
        {
            if (value != _category)
            {
                _category = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion Category Property
}

public class ViewModel
{
    public ViewModel()
    {
        Items.Add(new Item { Name="Alan"});
        Items.Add(new ItemSubClass { Name = "Bob", Category = "Whatever" });
        Items.Add(new Item { Name = "Charlie" });
    }

    public ObservableCollection<Item> Items { get; private set; }
        = new ObservableCollection<Item>();
}

截图:

enter image description here