如何在WPF的DataGrid中创建空的分组?

3
我在WPF中有一个DataGrid,基于某个属性分组,但我希望即使没有相应的项,也要有一些分组存在。
我的代码基于这个,但在DataGrid上不起作用。
<Window
x:Class="EmptyGroups.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Servers by cluster"
WindowStartupLocation="CenterScreen">

<DockPanel>

    <WrapPanel DockPanel.Dock="Top" Background="BlanchedAlmond">
        <Label Content="Cluster name:" Margin="10"/>
        <TextBox x:Name="NewClusterName" Text="type new cluster name here" MinWidth="50" BorderThickness="1" Margin="10"/>
        <Button Content="Add cluster" Click="AddNewCluster_Click" Margin="10"/>
    </WrapPanel>

    <ListView x:Name="ServersList">

        <ListView.GroupStyle>
            <GroupStyle HidesIfEmpty="False">
                <GroupStyle.ContainerStyle>
                    <Style TargetType="GroupItem">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="GroupItem">
                                    <Expander IsExpanded="True">
                                        <Expander.Header>
                                            <TextBlock TextWrapping="Wrap" Margin="0,10,0,5" >
                                                <Bold><TextBlock Text="{Binding Name}"/></Bold> (<TextBlock Text="{Binding ItemCount}"/> servers)
                                            </TextBlock>
                                        </Expander.Header>
                                        <ItemsPresenter/>
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </ListView.GroupStyle>

        <ListView.View>
            <GridView>
                <GridViewColumn Header="Server" DisplayMemberBinding="{Binding Name}"/>
                <GridViewColumn Header="Cluster" DisplayMemberBinding="{Binding Cluster.Name}"/>
            </GridView>
        </ListView.View>
    </ListView>

    <DataGrid Name="ServersGrid" AutoGenerateColumns="False" IsReadOnly="True">
        <DataGrid.GroupStyle>
            <GroupStyle HidesIfEmpty="False">
                <GroupStyle.Panel>
                    <ItemsPanelTemplate>
                        <DataGridRowsPresenter/>
                    </ItemsPanelTemplate>
                </GroupStyle.Panel>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <TextBlock Text="" Width="20" />
                            <TextBlock Text="{Binding Path=Name}"/>
                        </DockPanel>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </DataGrid.GroupStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="ServerGrid" Binding="{Binding Name}" />
            <DataGridTextColumn Header="ClusterGrid" Binding="{Binding Cluster.Name}"/>
        </DataGrid.Columns>
    </DataGrid>
</DockPanel>

并且 Windows1.xaml.cs 文件 :
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Data;

namespace EmptyGroups
{
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        var clusters = new[]
        {
            new Cluster { Name = "Front end" },
            new Cluster { Name = "Middle end" },
            new Cluster { Name = "Back end" },
        };

        var collectionView = new ListCollectionView(new[]
        {
            new Server { Cluster = clusters[0], Name = "webshop1" },
            new Server { Cluster = clusters[0], Name = "webshop2" },
            new Server { Cluster = clusters[0], Name = "webshop3" },
            new Server { Cluster = clusters[0], Name = "webshop4" },
            new Server { Cluster = clusters[0], Name = "webshop5" },
            new Server { Cluster = clusters[0], Name = "webshop6" },
            new Server { Cluster = clusters[2], Name = "sql1" },
            new Server { Cluster = clusters[2], Name = "sql2" },
        });

        var groupDescription = new PropertyGroupDescription("Cluster.Name");

        // this foreach must at least add clusters that can't be
        // derived from items - i.e. groups with no items in them
        foreach (var cluster in clusters)
            groupDescription.GroupNames.Add(cluster.Name);

        collectionView.GroupDescriptions.Add(groupDescription);
        ServersList.ItemsSource = collectionView;
        ServersGrid.ItemsSource = collectionView;
        Clusters = groupDescription.GroupNames;
    }

    readonly ObservableCollection<object> Clusters;

    void AddNewCluster_Click(object sender, RoutedEventArgs e)
    {
        Clusters.Add(NewClusterName.Text);
    }
}

class Cluster
{
    public string Name { get; set; }
}

class Server
{
    public Cluster Cluster { get; set; }
    public string Name { get; set; }
}
}

在添加6个后,DataGrid停止显示所有空组。谢谢。


我刚刚添加了代码,似乎一个DataGrid不能有比项更多的组,这似乎是一个WPF bug。 - hokkos
1
在这种情况下,我会考虑创建一个“NullServer”和/或“EmptyCluster”,并为这些值/类型定义自定义样式/模板。 - Jake Berger
你有没有找到解决方案? - Jonas Sourlier
是的,由于 WPF DataGrid 中存在一个错误,所以不能有比项更多的组,因此我们为每个存在或不存在的组添加一个虚拟项,并将它们的可见性设置为折叠。 - hokkos
1个回答

1

在回答一个问题之后,我自己解决了它。由于 WPF DataGrid 中存在一个 bug,分组数不能超过项数,因此我们为每个存在或不存在的组添加一个幽灵项,并将它们的可见性设置为折叠。


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