How to add toolbar to bottom, top, left, or right of the inside of a listbox in WPF?
-
13-09-2019 - |
Question
I have a listbox with a style that has rounded corners. I'd like to add a toolbar inside the listbox that pertains to that specific list box. Currently, if I add a toolbar inside the grid that contains a listbox, it will overlap the last item in the row (depending on the height of the toolbar). Does anyone have any ideas on the best way to implement this? I know I could create a border control that matches the look of the listbox edges and then place a listbox that has a style without borders inside the main border stacked with the toolbar at the bottom, but I'm hoping there is a better way to keep my current listbox style and just place a toolbar inside the bottom of the listbox that doesn't hide any listbox items.
Thanks,
John
Solution
Not sure I follow entirely, but I think you have a couple of options:
- Integrate the
ToolBar
into theListBox
template, probably by writing a control that extendsListBox
and adds a property to set theToolBar
items. - Turn off the
Border
on theListBox
and stick your ownBorder
around it that also encompasses theToolBar
.
2 is a little easier and is probably what you want.
Example of 1
(I didn't bother subclassing ListBox here - I just hard-coded some ToolBar items instead)
<Grid Margin="10">
<ListBox>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="1,1,1,1" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True" CornerRadius="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToolBarTray Background="White">
<ToolBar Band="1" BandIndex="1">
<Button>
Cut
</Button>
<Button>
Copy
</Button>
<Button>
Paste
</Button>
</ToolBar>
<ToolBar Band="2" BandIndex="1">
<Button>
Undo
</Button>
<Button>
Redo
</Button>
</ToolBar>
</ToolBarTray>
<ScrollViewer Grid.Row="1" Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="Panel.Background" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.ControlBrushKey}" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ItemsControl.IsGrouping" Value="True">
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ListBox.Template>
<ListBoxItem>One</ListBoxItem>
<ListBoxItem>Two</ListBoxItem>
<ListBoxItem>Three</ListBoxItem>
</ListBox>
</Grid>
Example of 2
<Grid Margin="10">
<Border CornerRadius="5" BorderThickness="1" BorderBrush="Black" Padding="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToolBarTray Background="White">
<ToolBar Band="1" BandIndex="1">
<Button>
Cut
</Button>
<Button>
Copy
</Button>
<Button>
Paste
</Button>
</ToolBar>
<ToolBar Band="2" BandIndex="1">
<Button>
Undo
</Button>
<Button>
Redo
</Button>
</ToolBar>
</ToolBarTray>
<ListBox Grid.Row="1" BorderThickness="0">
<ListBoxItem>One</ListBoxItem>
<ListBoxItem>Two</ListBoxItem>
<ListBoxItem>Three</ListBoxItem>
</ListBox>
</Grid>
</Border>
</Grid>
In both cases, the result looks similar:
alt text http://img42.imageshack.us/img42/372/screenshotof.png
OTHER TIPS
Most likely you have something declared wrong in your code if things are being overlapped visually. You should have your ListBox declared with Grid.Row="0" and your toolbar as Grid.Row="1" (or something similar) if you'd like them not to overlap. This MSDN article explains grid layouts well.
If your ListBoxItems are not databound, you can just add a ListBoxItem with a custom style as the last item in your list. Otherwise you can use a DataTemplateSelector to format your item styles based on the content bound within.