GUI Design
Make the WPF GridSplitter Work Correctly!
You can find lots of articles explaining how to use a WPF GridSplitter, but the ones I’ve seen never work quite right. Actually, they seem to work until you add some more realistic code, and then things start going haywire! In this post I explain a couple of gotcha’s, plus one nifty trick to give your splitter a 3-d appearance.
The First Gotcha – The Wrong Column Stretches!
If you are trying your first GridSplitter, chances are you will omit a tag that looks completely unnecessary: the HorizontalAlignment tag (or, if you are splitting rows, the VerticalAlignment tag). If you omit that tag, your screen will look like this when you drag the splitter:
The correct XAML looks like this:
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="10" ToolTip="Drag left-right to resize"
HorizontalAlignment="Stretch" />
Why do you need that tag? I wish I knew, I’ve never seen it discussed.
Gotcha Number Two
The next problem you’ll need to fight is when the wrong columns (or rows) get resized, or when nothing is resized whatsoever! Generally this happens when
- You have 3 columns…
- Your middle column holds the splitter…
- And you auto-size either column zero, column 2, or both!
Important principle:If you specify the size of any row or column, even autosizing it, the GridSplitter cannot change it’s size!
Further, if you have more than three columns, you should make sure that exactly two of them lack any width specification; they will be resized. If you have 4, 5, or more columns, please specify a width, typically ‘width=Auto”‘.
Tip: Give Your GridSplitter a 3-d Appearance
Even with a tool tip, your users might not realize that they should drag your GridSplitter around. (But they might get frustrated try knocking it around!) But, make it look 3-d and they will cotton-on pretty quick. The best way to do that is to
- Use an ImageBrush for your background
- If you’re using an older version of WPF, specify TileMode=”Tile” for the brush
- I like to save a bit on resources and use the smallest possible image for my background (such as 8×1 pixels), letting the tile mode spread it across the available area.
Here is the XAML:
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="10" ToolTip="Drag left-right to resize" HorizontalAlignment="Center"> <GridSplitter.Background> <ImageBrush ImageSource="/SplitterSample;component/Images/Splitter8x1.jpg" /> </GridSplitter.Background> </GridSplitter>
Here is what my background image looks like (magnified 8x):
WPF will stretch (tile) your image to fill the available space, causing your image to magically appear like a 3-d bar!
Code Listing
Finally, here is the full XAML. If you wish to try it, make sure you create a sub-folder in your project named ‘Images’ and place your background image in that folder. Also, replace ‘SplitterSample’ with your project name where the ImageBrush is referenced.
<Window x:Class="SplitterSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStartupLocation="CenterScreen" Title="Grid Splitter Sample" Height="150" Width="325"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBlock Background="LightGoldenrodYellow" Text="This is the left-hand side" /> <GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="10" ToolTip="Drag left-right to resize" HorizontalAlignment="Center" > <GridSplitter.Background> <ImageBrush ImageSource="/SplitterSample;component/Images/Splitter8x1.jpg" /> </GridSplitter.Background> </GridSplitter> <TextBlock Grid.Column="2" Background="Linen" Text="This is the right-hand side" /> </Grid> </Window>