使用这些类:
public class Person
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class Employee : Person
{
public string JobTitle { get; set; }
}
public class Customer : Person
{
public string CustomerID { get; set; }
}
这个ViewModel类:
public class MainViewModel
{
public ObservableCollection<Person> Persons { get; set; }
}
如何设计我的观点,以便我可以将MainViewModel.Persons
的元素按其派生类Type
分组,并为每个分组显示<ContentControl>
,<ContentControl>
应该根据{{1}}属于特定群组的内容,使用不同的DataTemplate
假设我有大量来自Type
的类,而我的Person
集合可以同时包含任何这些派生类。
如果可能,我还希望能够在XAML中声明我的各种MainViewModel.Persons
。
答案 0 :(得分:1)
您可以使用DataType构建三个不同的DataTemplates。它将自动选择最派生类型的模板。一个缺点是你的模板会有点重复,因为每个模板都可以重新定义Person模板提供的基本信息。
要对数据进行分组,您有两种方法:
如果你想使用选项1,你可以使用LINQ的GroupBy方法,例如
Persons.GroupBy(_ => _.GetType())
然后按下它进入一个ObservableCollection。但是,如果您的人员集合在加载屏幕后发生更改,则必须重建整个集合或订阅CollectionChanged事件并自行同步更改。
我会建议选项2,因为它神奇且令人敬畏。在CollectionViewSource上将IsLiveGroupingRequested设置为true时,WPF应自动为您处理分组。但是,为了适应这种情况,我在Person对象中添加了一个新属性:PersonType。 (如果你最终本地化了你的应用程序,那么这比使用类型名更好!)
<ItemsControl>
<ItemsControl.Resources>
<CollectionViewSource x:Key="viewSource" Source="{Binding Path=Persons}" IsLiveGroupingRequested="True">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="PersonType" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate DataType="{x:Type myNamespace:Person}"> ... </DataTemplate>
<DataTemplate DataType="{x:Type myNamespace:Employee}"> ... </DataTemplate>
<DataTemplate DataType="{x:Type myNamespace:Customer}"> ... </DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<Binding Source="{StaticResource viewSource}" />
</ItemsControl.ItemsSource>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Margin" Value="5" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontSize="20" Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
注意额外的命名空间:
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
答案 1 :(得分:0)
这是一个可能的答案,“我如何设计我的视图,以便我可以按其派生类类型对MainViewModel.Persons的元素进行分组?”
static void Main(string[] args)
{
List<Person> Persons = new List<Person>() { new Employee("john","smith"), new Customer("jane","smoth"), new Person("jack","smath") };
Dictionary<object, List<Person>> objectTypeToListOfThoseObjects = new Dictionary<object, List<Person>>();
// Build dictionary of "types" that maps from type to a list of all people of that type
foreach (var person in Persons)
{
var personType = person.GetType();
if (!objectTypeToListOfThoseObjects.Keys.Contains(personType))
{ objectTypeToListOfThoseObjects.Add(personType, new List<Person>()); }
}
// Group each person by their derived Type by adding persons to the correct dictionary list
foreach (var person in Persons)
{
objectTypeToListOfThoseObjects[person.GetType()].Add(person);
}
foreach (var personType in objectTypeToListOfThoseObjects.Keys)
{
Console.WriteLine($"All people with derived type {personType}:");
foreach (var people in objectTypeToListOfThoseObjects[personType])
{
Console.WriteLine($"{people.LastName}, {people.FirstName}");
}
}
Console.ReadLine(); // pause the console
}
打印出来:
All people with derived type ConsoleApplication2.Employee:
smith, john
All people with derived type ConsoleApplication2.Customer:
smoth, jane
All people with derived type ConsoleApplication2.Person:
smath, jack