简体   繁体   English

如何在 WPF ListBox 中添加标题

[英]How to add headers in WPF ListBox

How does one add a header in a ListBox in WPF?如何在 WPF 的 ListBox 中添加标题? I have the below code and where the "Header - .." text is I'd like a header/group name of all the items below up to the next header:我有下面的代码,其中“标题 - ..”文本是我想要下面所有项目的标题/组名称,直到下一个标题:

<ListBox 
x:Name="ItemsListBox" 
Margin="0 16 0 16"
Style="{StaticResource MaterialDesignNavigationPrimaryListBox}">
<ListBox.Resources>
<Style TargetType="ScrollBar" BasedOn="{StaticResource MaterialDesignScrollBarMinimal}"/>
</ListBox.Resources>
Header - Config
<Separator/>
<ListBoxItem>Config menu 1</ListBoxItem>
<ListBoxItem>Config menu 2</ListBoxItem>
<ListBoxItem>Config menu 3</ListBoxItem>
<ListBoxItem>Config menu 4</ListBoxItem>
<ListBoxItem>Config menu 5</ListBoxItem>
<ListBoxItem>Config menu 6</ListBoxItem>
<ListBoxItem>Config menu 7</ListBoxItem>
Header - Tasks
<Separator/>
<ListBoxItem>Task menu 1</ListBoxItem>
<ListBoxItem>Task menu 2</ListBoxItem>
<ListBoxItem>Task menu 3</ListBoxItem>
<ListBoxItem>Task menu 4</ListBoxItem>
<ListBoxItem>Task menu 5</ListBoxItem>
<ListBoxItem>Task menu 6</ListBoxItem>
<ListBoxItem>Task menu 7</ListBoxItem>
<Separator/>
</ListBox>

Below is an example of what I'd like to achieve:下面是我想要实现的一个例子:

在此处输入图片说明

It doesn't neccesarily need to have icons with each listbox item, but mainly the headers like Options, User Settings and Administraton.它不需要每个列表框项目都有图标,但主要是选项、用户设置和管理等标题。

I'm only seeing other threads where people have multiple columns, but that creates two columns with different data and I would like to have 1 column but just add headers in bold and size higher font to separate the different menus from each other.我只看到人们有多个列的其他线程,但这会创建两列具有不同数据的列,我想要 1 列,但只需添加粗体和更大字体的标题以将不同的菜单彼此分开。

I'm using the MaterialDesign Theme for WPF - whether that is of any importance or relevance...我正在为 WPF 使用 MaterialDesign 主题 - 无论这是否重要或相关...

Thanks!谢谢!

EDIT 1: As I haven't mentioned before - it doesn't have to be a ListBox, I used it as it is used in the code I used to write my menu:编辑 1:正如我之前没有提到的 - 它不必是一个列表框,我使用它,因为它在我用来编写菜单的代码中使用:

    <materialDesign:DrawerHost
        IsLeftDrawerOpen="{Binding ElementName=MenuToggleButton, Path=IsChecked}">
        <materialDesign:DrawerHost.LeftDrawerContent>
            <DockPanel MinWidth="220">
                <ToggleButton 
                    Style="{StaticResource MaterialDesignHamburgerToggleButton}" 
                    DockPanel.Dock="Top"
                    HorizontalAlignment="Right" 
                    Margin="16"
                    IsChecked="{Binding ElementName=MenuToggleButton, Path=IsChecked, Mode=TwoWay}"/>

                <TextBox 
                    x:Name="DemoItemsSearchBox"
                    Text="{Binding SearchKeyword, UpdateSourceTrigger=PropertyChanged}"
                    DockPanel.Dock="Top"
                    Margin="16, 4"
                    Width="200"
                    materialDesign:HintAssist.Hint="Search"
                    materialDesign:HintAssist.IsFloating="True"
                    materialDesign:TextFieldAssist.HasClearButton="True"
                    materialDesign:TextFieldAssist.HasOutlinedTextField="True"
                    materialDesign:TextFieldAssist.DecorationVisibility="Collapsed"
                    materialDesign:TextFieldAssist.TextFieldCornerRadius="4"/>

                <ListBox 
                    x:Name="ItemsListBox" 
                    Margin="0 16 0 16"
                    Style="{StaticResource MaterialDesignNavigationPrimaryListBox}">
                    <ListBox.Resources>
                        <Style TargetType="ScrollBar" BasedOn="{StaticResource MaterialDesignScrollBarMinimal}"/>
                    </ListBox.Resources>
                -- This is where the ListBox items would be --
                </ListBox>
            </DockPanel>
        </materialDesign:DrawerHost.LeftDrawerContent>

        <DockPanel>
            <materialDesign:ColorZone
                Padding="16"
                materialDesign:ShadowAssist.ShadowDepth="Depth2"
                Mode="PrimaryMid"
                DockPanel.Dock="Top">
                <DockPanel>
                    <StackPanel Orientation="Horizontal">
                        <ToggleButton
                            x:Name="MenuToggleButton"
                            Style="{StaticResource MaterialDesignHamburgerToggleButton}"
                            IsChecked="False"
                            Click="MenuToggleButton_OnClick"
                            AutomationProperties.Name="HamburgerToggleButton"/>
                    </StackPanel>

                    <materialDesign:PopupBox
                        DockPanel.Dock="Right"
                        PlacementMode="BottomAndAlignRightEdges"
                        StaysOpen="False">

                        <StackPanel>
                            <Grid Margin="10">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    <RowDefinition />
                                </Grid.RowDefinitions>
                                <TextBlock
                                    Text="Light"
                                    Margin="0 0 10 0"/>
                                <ToggleButton
                                    x:Name="DarkModeToggleButton"
                                    Click="MenuDarkModeButton_Click"
                                    Grid.Column="1"/>
                                <TextBlock
                                    Text="Dark"
                                    Margin="10 0 0 0"
                                    Grid.Column="2"/>
                                <TextBlock
                                    Text="Enabled"
                                    Margin="0 10 10 0"
                                    Grid.Row="1"/>
                                <ToggleButton
                                    x:Name="ControlsEnabledToggleButton"
                                    Margin="0 10 0 0"
                                    IsChecked="{Binding ControlsEnabled}"
                                    Grid.Row="1"
                                    Grid.Column="1"/>
                            </Grid>

                            <Separator/>

                            <Button
                                Content="Hello World"
                                />

                            <Button
                                Content="Nice Popup"
                                />

                            <Button
                                Content="Can't Touch This"
                                IsEnabled="False"/>

                            <Separator/>

                            <Button
                                Content="Goodbye"
                                />
                        </StackPanel>
                    </materialDesign:PopupBox>

                    <TextBlock
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        FontSize="22"
                        Margin="-152,0,0,0"
                        Text="Hi"/>
                </DockPanel>
            </materialDesign:ColorZone>

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>

                <ScrollViewer
                    x:Name="MainScrollViewer"
                    Grid.Row="1"
                    materialDesign:ScrollViewerAssist.IsAutoHideEnabled="True"
                    HorizontalScrollBarVisibility="{Binding SelectedItem.HorizontalScrollBarVisibilityRequirement, FallbackValue=Disabled}"
                    VerticalScrollBarVisibility="{Binding SelectedItem.VerticalScrollBarVisibilityRequirement, FallbackValue=Disabled}" >
                    <ContentControl
                        Margin="{Binding MarginRequirement, FallbackValue=16}"/>
                </ScrollViewer>

                <materialDesign:Snackbar
                    x:Name="MainSnackbar"
                    MessageQueue="{materialDesign:MessageQueue}"
                    Grid.Row="1"/>
            </Grid>
        </DockPanel>
    </materialDesign:DrawerHost>

Probably not my Final answer, as still uses the MVVM from the demo, but using the demo project:可能不是我的最终答案,因为仍然使用演示中的 MVVM,但使用演示项目:

in the MainWindowViewModel.cs, add public ListCollectionView DemoLCV { get; }在 MainWindowViewModel.cs 中,添加public ListCollectionView DemoLCV { get; } public ListCollectionView DemoLCV { get; } after public ObservableCollection<DemoItem> DemoItems { get; } public ListCollectionView DemoLCV { get; }public ObservableCollection<DemoItem> DemoItems { get; } public ObservableCollection<DemoItem> DemoItems { get; }

and add并添加

DemoLCV = new ListCollectionView(DemoItems);
DemoLCV.GroupDescriptions.Add(new PropertyGroupDescription("Name"));

after

MoveNextCommand = new AnotherCommandImplementation(
           _ =>
           {
               if (!string.IsNullOrWhiteSpace(SearchKeyword))
                   SearchKeyword = string.Empty;

               SelectedIndex++;
           },
           _ => SelectedIndex < DemoItems.Count - 1);

then in the MainWindow.xaml amend the ListBox to:然后在 MainWindow.xaml 中将 ListBox 修改为:

                    <ListBox 
                    x:Name="DemoItemsListBox" 
                    Margin="0 16 0 16"
                    SelectedIndex="{Binding SelectedIndex}"
                    SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}"
                    ItemsSource="{Binding DemoLCV}"
                    PreviewMouseLeftButtonUp="UIElement_OnPreviewMouseLeftButtonUp"
                    AutomationProperties.Name="DemoPagesListBox"
                    Style="{StaticResource MaterialDesignNavigationPrimaryListBox}">
                    <ListBox.Resources>
                        <Style TargetType="ScrollBar" BasedOn="{StaticResource MaterialDesignScrollBarMinimal}"/>
                    </ListBox.Resources>
                    <ListBox.GroupStyle>
                        <GroupStyle>
                            <GroupStyle.HeaderTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Name}" />
                                </DataTemplate>
                            </GroupStyle.HeaderTemplate>
                        </GroupStyle>
                    </ListBox.GroupStyle>
                    <ListBox.ItemTemplate>
                        <DataTemplate DataType="domain:DemoItem">
                            <TextBlock Text="{Binding Name}" Margin="24 4 0 4" AutomationProperties.AutomationId="DemoItemPage"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

This adds the menu item name as a category heading for each item.这将添加菜单项名称作为每个项目的类别标题。

This is just to demonstrate the concept.这只是为了演示这个概念。

to expand on the idea, with useful headings, add another property to the DemoItem class, eg categoryName, and populate this with the different categories on initialisation of the DemoItems collection.为了扩展这个想法,使用有用的标题,向 DemoItem 类添加另一个属性,例如 categoryName,并在初始化 DemoItems 集合时使用不同的类别填充它。

Then change DemoLCV.GroupDescriptions.Add(new PropertyGroupDescription("Name"));然后更改DemoLCV.GroupDescriptions.Add(new PropertyGroupDescription("Name")); in this example to DemoLCV.GroupDescriptions.Add(new PropertyGroupDescription("categoryName"));在这个例子中DemoLCV.GroupDescriptions.Add(new PropertyGroupDescription("categoryName")); to group by your categories.按类别分组。

You can then play with the style of the TextBlock in the ListBox.GroupStyle to display the heading as desired.然后,您可以使用 ListBox.GroupStyle 中 TextBlock 的样式来根据需要显示标题。

I'll try and pop in an example later, plus see if I can come up with a non-MVVM option.稍后我将尝试弹出一个示例,另外看看我是否可以提出非 MVVM 选项。

For a hardcoded xaml, non-MVVM solution, I would use a Menu instead of a ListBox.对于硬编码的 xaml 非 MVVM 解决方案,我将使用 Menu 而不是 ListBox。 I generally only use ListBoxes for binding to lists of data/items.我通常只使用 ListBoxes 绑定到数据/项目列表。

We can also achieve your icons with this method.我们也可以用这种方法来实现你的图标。

Obviously, style to your liking, but if you take out your ListBox, you can replace with Menu as follows:显然,风格随你喜欢,但如果你拿出你的 ListBox,你可以用 Menu 替换,如下所示:

                <ScrollViewer>
                    <Menu>
                        <Menu.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel />
                            </ItemsPanelTemplate>
                        </Menu.ItemsPanel>
                        <Menu.Resources>
                            <Style TargetType="ScrollBar" BasedOn="{StaticResource MaterialDesignScrollBarMinimal}"/>
                        </Menu.Resources>
                        <TextBlock Text="Config" FontWeight="Bold" FontSize="20" IsEnabled="False"  />
                        <Separator/>
                        <MenuItem>
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 1" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem >
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 2" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem >
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 3" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem >
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 4" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem >
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 5" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem >
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 6" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem >
                            <MenuItem.Header>
                                <DockPanel>
                                    <materialDesign:PackIcon Kind="Settings" Margin="3" />
                                    <TextBlock Text="Config item 7" Margin="3" />
                                </DockPanel>
                            </MenuItem.Header>
                        </MenuItem>
                        <TextBlock Text="Tasks" FontWeight="Bold" FontSize="20"  />
                        <Separator/>
                        <MenuItem Header="Task item 1" />
                        <MenuItem Header="Task item 2" />
                        <MenuItem Header="Task item 3" />
                        <MenuItem Header="Task item 4" />
                        <MenuItem Header="Task item 5" />
                        <MenuItem Header="Task item 6" />
                        <MenuItem Header="Task item 7" />
                    </Menu>
                </ScrollViewer>

This produces (I have only added icons to the top half, to illustrate how):这会产生(我只在上半部分添加了图标,以说明如何):

菜单截图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM