xaml - ListView 中多种项目类型的 UWP DataTemplates

标签 xaml listview win-universal-app datatemplate

我将如何实现呢?

假设这是我的模型:

public interface IAnimal
{
     string Name { get; }
}
public class Fish : IAnimal
{
    public string Name { get; set; }
    public int ScalesCount { get; set; }
}
public class Dog : IAnimal
{
    public string Name { get; set; }
    public string CollarManufacturerName { get; set; }
}

public class ViewModel
{
    public ObservableCollection<IAnimal> Animals { get; set; }

    public ViewModel()
    {
        this.Animals = new ObservableCollection<IAnimal>();
        this.Animals.Add(new Fish { Name = "Carl", ScalesCount = 9000 });
        this.Animals.Add(new Dog { Name = "Fifi", CollarManufacturerName = "Macrosoft" });
    }
}

为了这个问题中的代码量,请假设 INotifyPropertyChanged在必要时实现,并且 ViewModel 在页面中正确初始化。

如何使用自己对应的 DataTemplates?在 WPF 中,我只定义多个没有 x:Key 的 DataTemplates但是使用定义的 DataType 并让 ListView 根据项目的类型选择使用哪个。 UWP 不喜欢这样。编译器只是声明 Dictionary Item "DataTemplate" must have a Key attribute .那么我该如何实现我的目标呢?

当前尝试

我目前的尝试是自定义 DataTemplateSelector ,这看起来相当简单。
public class MyDataTemplateSelector: Windows.UI.Xaml.Controls.DataTemplateSelector
{
    public ObservableCollection<TemplateMatch> Matches { get; set; }

    public DataTemplateSelector()
    {
        this.Matches = new ObservableCollection<TemplateMatch>();
    }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        return this.Matches.FirstOrDefault(m => m.TargetType.Equals(item))?.Template;
    }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        return this.Matches.FirstOrDefault(m => m.TargetType.Equals(item))?.Template;
    }
}

public class TemplateMatch
{
    public Type TargetType { get; set; }
    public DataTemplate Template { get; set; }
}

像这样在 XAML 中定义它:
<ListView ItemsSource="{x:Bind ViewModel.Animals}">
    <ListView.ItemTemplateSelector>
        <cmp:MyDataTemplateSelector>
            <cmp:MyDataTemplateSelector.Matches>
                <cmp:TemplateMatch TargetType="model:Dog" Template="{StaticResource DogTemplate}"/>
                <cmp:TemplateMatch TargetType="model:Fish" Template="{StaticResource FishTemplate}"/>
            </cmp:MyDataTemplateSelector.Matches>
        </cmp:MyDataTemplateSelector>
    </ListView.ItemTemplateSelector>
</ListView>

不幸的是,当我运行它时,运行时出现异常,说明 Failed to create a 'Ui.Components.TemplateMatch' from the text 'model:Dog'.所以它似乎绑定(bind)到 Type属性(property)没那么容易。

任何帮助表示赞赏!

请注意,我想使用类型为 Type 的属性。 ,而不是 string我将传递 CLR 类型名称并使用反射来调用该类型,主要是因为我不希望混合的 CLR 和 XML 命名空间出现在 XAML 中。如果您能找到一种使用 XML 命名空间调用该类型的方法,我很乐意将其作为答案。

最佳答案

我找到了解决方法。如果您能够创建这些类型的实例 - 您可以使用它来检测类型:

[ContentProperty(Name = nameof(Matches))]
public class TypeTemplateSelector : DataTemplateSelector
{
    public ObservableCollection<TemplateMatch> Matches { get; set; }
    public TypeTemplateSelector()
    {
        this.Matches = new ObservableCollection<TemplateMatch>();
    }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        return this.Matches.FirstOrDefault(m => m.ItemOfType.GetType().Equals(item.GetType()))?.TemplateContent;
    }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        return this.Matches.FirstOrDefault(m => m.ItemOfType.GetType().Equals(item.GetType()))?.TemplateContent;
    }
}

[ContentProperty(Name = nameof(ItemOfType))]
public class TemplateMatch
{
    public object ItemOfType { get; set; }
    public DataTemplate TemplateContent { get; set; }
}

XAML:
<controls:TypeTemplateSelector>
    <controls:TemplateMatch TemplateContent="{StaticResource FishTemplate}">
        <models:Fish/>
    </controls:TemplateMatch>
    <controls:TemplateMatch TemplateContent="{StaticResource DogTemplate}">
        <models:Dog/>
    </controls:TemplateMatch>
</controls:TypeTemplateSelector>

关于xaml - ListView 中多种项目类型的 UWP DataTemplates,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32414233/

相关文章:

push-notification - UWP 中添加 PushNotificationType.TileFlyout。它是什么?

c# - Xamarin - 将命令绑定(bind)到用户控件内对象的属性

WPF XAML - 行根本不显示

wpf - 链接依赖属性

Android ListView 滚动条

Android 自定义 ListView - 更改所选项目的背景和文本颜色不起作用?

c# - 如何在 Windows 8.1 中使用 SettingsFlyout 的完整高度和宽度

wpf - 为什么在这种情况下无法解析 StaticResource?

android - 如何在 android 中关闭搜索 View 后重置 ListView ?

c# - 在 Windows 10 中共享目标 Universal Apps Template10 方法