数据网格绑定/分组

时间:2018-04-01 16:37:00

标签: c# wpf datagrid

我的ViewModel&#34; MainWindowModel&#34;中有一个Persons类型ObservableCollection<Person>的对象。在MainWindow中,我想要一个带有分组的DataGrid&#34; Sex&#34;。但是,在群组标题中总会出现&#34; M&#34;为性:  enter image description here

数据绑定中是否有错误?

<Window ...
    xmlns:viewmodel="clr-namespace:SimpleDatagridGrouping"

<Window.Resources>
    <viewmodel:MainWindowModel x:Key="vm" />

    <CollectionViewSource x:Key="cvsPersons" 
        Source="{Binding  Source={StaticResource vm}, Path=Persons}">
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="Sex"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>

    <DataTemplate x:Key="GroupingHeader">
        <StackPanel Background="YellowGreen" Orientation="Horizontal" 
                    HorizontalAlignment="Left">
            <TextBlock Text="Sex" Margin="5,5,5,5"/>
            <TextBlock  Margin="0,5,5,5"
                        Text="{Binding Source={StaticResource  cvsPersons}, 
                        Path=Sex}"/>
            <TextBlock Text="Count" Margin="5,5,5,5"/>
            <TextBlock Margin="0,5,5,5" Text="{Binding Path=ItemCount}"/>
        </StackPanel>
    </DataTemplate>

</Window.Resources>

<Grid  DataContext="vm">
    <DataGrid ItemsSource="{Binding Source={StaticResource ResourceKey=cvsPersons}}"
              SelectionMode="Single" 
              Margin="10,0,10,10" 
              AlternationCount="2"                  
              VerticalContentAlignment="Center"
              AutoGenerateColumns="False"
              MinHeight="35">
        <DataGrid.GroupStyle>
            <GroupStyle HeaderTemplate="{StaticResource ResourceKey=GroupingHeader}"/>
        </DataGrid.GroupStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Forename" Binding="{Binding Forename}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
            <DataGridTextColumn Header="Age" Binding="{Binding Age}" />
            <DataGridTextColumn Header="Sex" Binding="{Binding Sex}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

视图模型:

public class Person
{
    public string Forename { get; set; }
    public string Name { get; set; }
    public Int32 Age { get; set; }
    public E_Sex Sex { get; set; }
    public Person(string forename_, string name_, Int32 age_, E_Sex sex_ )
        {...}
}//eoClass: Person

public class MainWindowModel : Notifier
{
    public MainWindowModel()
    {
        IList<Person> persons_ = new List<Person> ();
        persons_.Add ( new Person ( "Hans", "Müller", 23, E_Sex.M ) );
        //...
        this.persons = new ObservableCollection<Person> ( persons_ );
    }//eoCtor

    private ObservableCollection<Person> persons = null;
    public ObservableCollection<Person> Persons
    {
        get { return this.persons; }
        set
        {
            this.persons = value;
            OnPropertyChanged ( "Persons" );
        }
    }
}//eoClass: MainWindowModel

2 个答案:

答案 0 :(得分:0)

当您进行分组时,您不会找到标题为模板的人。 你得到的是一个名为Name的属性。 在你的团体风格中,你期望得到一个人并绑定它的属性:

<DataTemplate x:Key="GroupingHeader">
            .....
            <TextBlock 
                Margin="0,5,5,5"
                Text="{Binding Source={StaticResource  cvsPersons}, Path=Sex}" 
                />

您的模板应该更像:

<DataTemplate x:Key="GroupingHeader">
            .....
            <TextBlock 
                Margin="0,5,5,5"
                Text="{Binding Name}"

您可以在此处查看完整示例: https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-group-sort-and-filter-data-in-the-datagrid-control

如果仔细查看输出图片,您会在标题中看到“Project ....”。这些是ProjectName。但代码绑定了Name。 那是因为您定义的任何排序描述符都是作为一种名为Name的特殊字段返回的。

答案 1 :(得分:0)

要获得预期结果,请将其用于您的群组标题DataTemplate

<DataTemplate x:Key="GroupingHeader">
    <StackPanel Background="YellowGreen" Orientation="Horizontal"
                HorizontalAlignment="Left">
            <TextBlock Text="Sex" Margin="5,5,5,5"/>
            <!--Bind to Name!!-->
            <TextBlock  Margin="0,5,5,5" Text="{Binding Path=Name}"/>
            <TextBlock Text="Count" Margin="5,5,5,5"/>
            <TextBlock Margin="0,5,5,5" Text="{Binding Path=ItemCount}"/>
    </StackPanel>
</DataTemplate>

那么这里发生了什么?当您在此特定DataTemplate中绑定时,您必须考虑组头的DataContext是什么,因为这是任何Binding查找的内容。所以当你说:Text="{Binding Source={StaticResource cvsPersons}, Path=Sex}"时,你会说找到StaticResource cvsPersons并绑定到其DataContext的名为Sex的属性。我必须承认,你所获得的行为有点奇怪,因为我认为绑定应该失败(如果我错了请纠正我),但看起来它找到了列表中的第一个人并使用了那个人的性别是所有标题的价值。试试吧,将列表中的第一个人更改为女性,现在所有标题都会显示F而不是M

那么群组标题的DataContext是什么?嗯,它被称为CollectionViewGroup,它具有以下公共属性:NameItemsItemCount。仔细观察,您已经在DataTemplate的最后ItemCount绑定到TextBlockName,是您所分组的任何内容的价值,在您的情况下是&#39; F&#39; M&#39; M&#39; ...逻辑上对于每个组都是唯一的,并且任何给定组中的每个项目对于该集合所归属的属性具有相同的值。