WPF - 按类型分组集合并按类型进行模板化

时间:2016-02-24 18:01:53

标签: c# wpf

使用这些类:

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

2 个答案:

答案 0 :(得分:1)

您可以使用DataType构建三个不同的DataTemplates。它将自动选择最派生类型的模板。一个缺点是你的模板会有点重复,因为每个模板都可以重新定义Person模板提供的基本信息。

要对数据进行分组,您有两种方法:

  1. ObservableCollection ObservableCollections
  2. CollectionViewSource
  3. 如果你想使用选项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