我将如何实现呢?
假设这是我的模型:
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/