c# - 在 WPF ListBox 中隐藏空组

标签 c# wpf listbox

我正在尝试进一步自定义 WPF ListBox 的内置功能以按组显示项目。

简而言之,如果组内的所有项目都已折叠(Visibility 属性),我想隐藏组的容器(以及组的标题)。

首先,我有一个非常简单的城市类,代表单个项目。此类包括 Shown 属性。在 ItemContainerStyle 中,我只有 DataTrigger,如果此属性的值为 False<,则将 Visibility 设置为 Collapsed/.

class City : INotifyPropertyChanged
{
    private bool m_Shown = true;

    public string Name { get; set; }
    public string Country { get; set; }

    public bool Shown
    {
        get
        {
            return m_Shown;
        }
        set
        {
            m_Shown = value;
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Shown"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

这就是我添加样本城市、添加群组描述的方式,一切正常。

m_cities = new List<City>
{
    new City() { Name = "Berlin", Country = "Germany" },
    new City() { Name = "Milano", Country = "Italy" },
    new City() { Name = "Frankfurt", Country = "Germany" },
    new City() { Name = "Rome", Country = "Italy" }
};

ICollectionView view = CollectionViewSource.GetDefaultView(m_cities);
view.GroupDescriptions.Add(new PropertyGroupDescription("Country"));
Cities = view; // <-- Binds to ItemsSource of ListBox

我尝试了几种方法来自动隐藏组,如果其中没有更多项目可见(全部折叠),但都没有成功。

一种方法是重复上面代码中的最后 3 行,这行得通,但我注意到使用此方法速度变慢,列表框必须对用户快速运行。

Bellow 是我的示例之一,这实际上用于隐藏,但之后我无法再让组可见。我尝试使用转换器和类似工具,但我无法让组再次可见

<ListBox.GroupStyle>
    <GroupStyle>
        <GroupStyle.ContainerStyle>
            <Style TargetType="{x:Type GroupItem}">
                <Style.Triggers>
                    <Trigger Property="ActualHeight" Value="20">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </Trigger>
                </Style.Triggers>
                <Setter Property="Visibility" Value="Visible"/>
                <Setter Property="MinHeight" Value="20"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type GroupItem}">
                            <StackPanel>
                                <TextBlock Text="{Binding Path=Name}"/>
                                <ItemsPresenter/>
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </GroupStyle.ContainerStyle>
    </GroupStyle>
</ListBox.GroupStyle>

感谢您的帮助。

最佳答案

这有点 (!) 晚了,但希望它能在将来帮助其他人。

在大多数(所有?)GroupItem 样式的控件模板中是一个 ItemsPresenter,用于托管和显示属于该组的子项目。按理说,如果所有子项都折叠起来,则此 ItemsPresenter 的高度将为零。

因此,您可以根据此条件向控件模板添加触发器,并相应地设置整个组项的Visibility。普通的属性触发器似乎不起作用,但数据触发器会。像这样:

<ControlTemplate>
    <StackPanel x:Name="Root">
        ...
        <ItemsPresenter x:Name="ItemsPresenter" />
        ...
    </StackPanel>
    <ControlTemplate.Triggers>
        <DataTrigger Binding="{Binding ActualHeight, ElementName=ItemsPresenter}" Value="0">
            <Setter TargetName="Root" Property="Visibility" Value="Collapsed" />
        </DataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

您需要命名控件模板的根元素(在此示例中,它是一个我命名为“Root”的 StackPanel 元素)以及 ItemsPresenter 元素(我刚刚将其称为“ItemsPresenter”)。显然,根元素可能是不同的类型,您可以使用任何您喜欢的名称。

您的方向是正确的,但您需要绑定(bind)到 ItemsPresenterActualHeight,并且它需要是数据触发器而不是普通的属性触发器。

关于c# - 在 WPF ListBox 中隐藏空组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50741677/

相关文章:

c# - 如何在 WPF 中使用关闭按钮关闭选项卡?

php - 在 PHP 中从列表框(多项选择)值创建数组

javascript - Microsoft JScript 运行时错误

c# - 无法连接到 SQL Server 数据库

WPF:标签未显示在后面的代码中

wpf - 为什么 TabControl.SelectedContent != (TabControl.SelectedItem as TabItem).Content?

delphi - 从列表框中选择一个代理(IDHTTP)

asp.net - 无法将列表框中的项目添加到列表

c# - 在c#中将字节转换为二进制字符串

c# - 从 WCF 服务调用进程以在 WCF 服务帐户下运行