GUI

Make the WPF GridSplitter Work Correctly!

Posted on Updated on

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.

I dragged the splitter to the right, squashing the right-hand side
Now I have dragged the splitter to the right, squashing the right-hand side
GridSplitter sample the left-hand content is squashed
GridSplitter sample: the left-hand content is squashed when I drag my splitter left

 

 

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:

This is how it looks when you omit the HorizontalAlignment tag
This is how it looks when you omit the HorizontalAlignment tag

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!

For column zero, I specified 'width="auto". You can see that it's size is not affected by my GridSplitter, whereas column 2, with no width setting, responds correctly
For column zero, I specified ‘width=”auto”. You can see that its size is not affected by my GridSplitter, whereas column 2, with no width setting at all, responds correctly.

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):

This image is only 1 pixel high; WPF stretches it to tile the whole range necessary
This image is only 1 pixel high; WPF stretches it to tile the whole range necessary.

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>