WPF数据网格分组样式

7
我在WPF中有以下的DataGrid,其中包含两个组别。
第一组是一个布尔标志,表示一个人是否处于活动/非活动状态。
第二组(或子组)是每个人的ID。 每个人可以有多个城市,因此需要按ID分组,因为每个人在DataGrid中会出现多次。 Table persons-cities 这里是XAML代码:
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding DataSource}">     
    <DataGrid.GroupStyle>                    
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander IsExpanded="True">
                                    <Expander.Style>
                                        <Style TargetType="{x:Type Expander}">    
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding Name}" Value="True">
                                                    <Setter Property="Background" Value="{StaticResource ActiveBrush}"/>
                                                </DataTrigger>
                                                <DataTrigger Binding="{Binding Name}" Value="False">
                                                    <Setter Property="Background" Value="{StaticResource InactiveBrush}"/>
                                                    <Setter Property="FontStyle" Value="Italic"/>
                                                    <Setter Property="Foreground" Value="Gray"/>
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </Expander.Style>
                                    <Expander.Header>
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock Text="{Binding Name, Converter={StaticResource BoolToTextConverter}}" Margin="5 2 5 2"/>
                                            <TextBlock Text=":" Margin="0 2 5 2"/>
                                            <TextBlock Text="{Binding ItemCount}" Margin="0 2 0 2"/>
                                        </StackPanel>
                                    </Expander.Header>
                                        <ItemsPresenter />
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Background="LightSteelBlue">
                        <TextBlock Text="{Binding Name}" Foreground="White" Margin="5 2 5 2"/>
                    </StackPanel>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </DataGrid.GroupStyle>
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel>
                        <DockPanel>
                            <Button BorderThickness="0" Content="Edit" Margin="3"
                                Command="{Binding Commands.Edit}"
                                CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                        </DockPanel>
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Header="ID" Binding="{Binding ID}" IsReadOnly="True"/>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True"/>
        <DataGridTextColumn Header="City" Binding="{Binding City}" IsReadOnly="True"/>                    
    </DataGrid.Columns>
</DataGrid>

一切正常! 但是我不喜欢每个子组的蓝色行。 我想要实现的是以下图片中的分组样式:

Table persons-cities

对于每个子组,我只希望每个人出现一次编辑按钮和ID。 我应该如何做?在XAML中是否有可能实现,还是应该在代码后端删除多余的内容?

编辑
这里是一些测试数据:

public class Person
{
    public Person(bool active, int id, string name, string city)
    {
        Active = active;
        ID = id;
        Name = name;
        City = city;
    }

    public bool Active { get; set; }
    public int ID { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;

        var data = new ObservableCollection<Person>
        {
            new Person(true, 233, "Max", "New York"),
            new Person(true, 233, "Max", "Los Angeles"),
            new Person(true, 314, "John", "Paris"),
            new Person(true, 578, "Mary", "Vienna"),
            new Person(true, 782, "Susan", "Rome"),
            new Person(true, 782, "Susan", "Prague"),
            new Person(true, 782, "Susan", "San Francisco"),
            new Person(false, 151, "Henry", "Chicago")
        };

        DataSource = new ListCollectionView(data);
    }

    private ListCollectionView _dataSource;

    public ListCollectionView DataSource
    {
        get { return _dataSource; }
        set
        {
            _dataSource = value;
            _dataSource.GroupDescriptions.Add(new PropertyGroupDescription("Active"));
            _dataSource.GroupDescriptions.Add(new PropertyGroupDescription("ID"));
        }
    } 

它们是不同的人 -> 它们在不同的城市。 - aybe
@ Aybe:不,每个人可以有多个城市,因此每个人在网格中会被显示多次。 - phil
1
你能提供测试数据的代码吗,这样我就可以重新创建它。 - Michal Ciechan
@Michal Ciechan:谢谢!我已经更新了我的答案。请参见上面的示例。 - phil
是的,但你现在展示它们的方式是错误的,这会导致误解。使用ItemsControl、ListBox或ComboBox来展示它们,这样每个用户只会有一行。 - aybe
1个回答

6

我强烈建议将数据结构更改为:

public class Person {
    public bool Active { get; set; }
    public int ID { get; set; }
    public string Name { get; set; }

    public Collection Cities { get; set; }
}

否则,您可以更改此GroupStyle
<GroupStyle>
    <GroupStyle.HeaderTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Background="LightSteelBlue">
                <TextBlock Text="{Binding Name}" Foreground="White" Margin="5 2 5 2"/>
            </StackPanel>
        </DataTemplate>
    </GroupStyle.HeaderTemplate>
</GroupStyle>

To

<GroupStyle>
    <GroupStyle.ContainerStyle>
        <Style TargetType="{x:Type GroupItem}">
            <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="EditButtonColumn" />
                        <ColumnDefinition SharedSizeGroup="IDColumn"  />
                        <ColumnDefinition SharedSizeGroup="NameColumn" />
                        <ColumnDefinition SharedSizeGroup="PresenterColumn" Width="*" />
                    </Grid.ColumnDefinitions>
                    <Button Grid.Column="0" BorderThickness="0" Content="Edit" Margin="3"
                CommandParameter="{Binding Path=Items[0]}" />
                    <TextBlock Grid.Column="1" Text="{Binding Path=Items[0].ID}" />
                    <TextBlock Grid.Column="2" Text="{Binding Path=Items[0].Name}" />

                    <ItemsPresenter Grid.Column="3" />
                </Grid>
                </ControlTemplate>
            </Setter.Value>
            </Setter>
        </Style>
    </GroupStyle.ContainerStyle>
</GroupStyle>

根据您的需求更改模板


我知道如何删除组标题,但如何像GroupStyle.HeaderTemplate中那样设置单元格样式?我想避免通过代码逐行遍历并编辑单元格。 - phil
谢谢!这正是我需要的 :) - phil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接