c# - How to add headers in WPF ListBox
问题描述
How does one add a header in a ListBox in WPF? 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.
I'm using the MaterialDesign Theme for WPF - whether that is of any importance or relevance...
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:
<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>
解决方案
For a hardcoded xaml, non-MVVM solution, I would use a Menu instead of a ListBox. I generally only use ListBoxes for binding to lists of data/items.
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:
<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):
推荐阅读
- html - 图像未显示 data-bg-src
- docker - 如何在 Nexus3 中为 GitLab 容器注册表配置 docker 代理存储库?
- sql - 内部连接多个表,但想要基于一列的不同数据
- c# - 对多个条目应用 Visual Studio 快速操作
- c++ - 如何拦截对 AfxThrowMemoryException 的所有调用
- python - 看似无错误的 python 代码运行时间过长
- c# - 进程无法访问该文件,因为它正被另一个进程使用
- javascript - 无法读取未定义的属性“获取”
- c - 用中间名分隔名字,用 strtok_r 分隔姓氏
- python-3.x - 如何计算 groupby 中位数并作为新列附加回数据框