【发布时间】:2015-09-05 14:32:14
【问题描述】:
我将如何实施?
假设这是我的模型:
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 在必要时实现,并且视图模型在页面中已正确初始化。
如何使用自己对应的 DataTemplates?在 WPF 中,我将只定义多个 DataTemplates,而不使用 x:Key,但使用已定义的 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'. 所以绑定到Type 属性似乎并不那么容易。
感谢任何帮助!
请注意,我想使用 Type 类型的属性,而不是 string,我将传递 CLR 类型名称并使用反射来调用类型,主要是因为我不想混合CLR 和 XML 命名空间出现在 XAML 中。如果你能找到一种使用 XML 命名空间调用类型的方法,我很乐意将其作为答案。
【问题讨论】:
-
您是否尝试过 TargetType="{x:Type model:Dog}" 因为该属性的类型是“Type”而不是字符串。
-
我做到了。 UWP 不再支持 x:Type 标记。那将是 WPF 的解决方案。 :)
-
为什么不在选择模板方法中创建条件语句,而不是使用 TemplateMatch?
-
我很想找到一个可以重复使用的解决方案。在 SelectTemplate 中选择特定类型违反了这个想法。这就是我希望能够在 XAML 中定义可用类型的原因。
-
我现在也遇到了同样的问题,你找到解决办法了吗?
标签: xaml listview win-universal-app datatemplate