Dan*_*mid 8 xaml listview datatemplate win-universal-app
我将如何实现这一目标?
让我们说这是我的模型:
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" });
}
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题中的代码量,请假设INotifyPropertyChanged在必要时实现,并且ViewModel在页面中正确初始化.
我如何使用自己的相应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; }
}
Run Code Online (Sandbox Code Playgroud)
像这样在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>
Run Code Online (Sandbox Code Playgroud)
不幸的是,当我运行它时,在运行时发生异常,说明Failed to create a 'Ui.Components.TemplateMatch' from the text 'model:Dog'.所以它似乎绑定到Type属性并不那么容易.
任何帮助表示赞赏!
请注意,我想使用类型的属性Type,而不是string传递CLR类型名称和使用反射来调用类型的属性,主要是因为我不希望在XAML中出现混合CLR和XML命名空间.如果您可以找到使用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; }
}
Run Code Online (Sandbox Code Playgroud)
XAML:
<controls:TypeTemplateSelector>
<controls:TemplateMatch TemplateContent="{StaticResource FishTemplate}">
<models:Fish/>
</controls:TemplateMatch>
<controls:TemplateMatch TemplateContent="{StaticResource DogTemplate}">
<models:Dog/>
</controls:TemplateMatch>
</controls:TypeTemplateSelector>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4478 次 |
| 最近记录: |