Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increase WPF GridSplitter mouse grabbing threshold

Is it possible to increase the distance from a grid splitter from which the user can grab it?

My splitter is only 1px in width. I would like to be able to grab the splitter from a greater distance.

As it is now i must point the mouse on the exact 1px line to grab it.

And the splitter must still be 1px in width

like image 212
ErikTJ Avatar asked Mar 14 '10 13:03

ErikTJ


3 Answers

You can change the actual size of the GridSplitter while keeping it looking like it's smaller. This will give you a 7 pixel width area to grab it while showing at 1 pixel:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="1"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <GridSplitter Grid.Column="1"
                  Margin="-3,0"
                  BorderThickness="3,0"
                  BorderBrush="Transparent"
                  HorizontalAlignment="Stretch" />
</Grid>

The example is using the method of giving the splitter its own column but the same principle applies if it's Left or Right aligned in a shared column.

like image 112
John Bowen Avatar answered Nov 12 '22 09:11

John Bowen


I know this is an ancient question but I thought I would add my answer anyway. After a lot of experimenting the following seems to work perfectly for a 1 pixel wide Gridsplitter

<ControlTemplate x:Key="gs0" TargetType="{x:Type GridSplitter}">
    <Border Margin="-5,0" Background="Transparent">
        <TextBlock Width="1"  Background="Green" />
    </Border>
</ControlTemplate>

Tested with the following code:

Grid HorizontalAlignment="Left"  >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition Width="1"/>
        <ColumnDefinition Width="200"/>
    </Grid.ColumnDefinitions>

<Grid Grid.Column="0">
    ....
</Grid>

<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" Template ="{StaticResource gs0}"/>

Without the template, the "mouse grabbing area" is 1 pixel. But set as above with the template, it is increased to 7 pixels which is about right. The same code can be adjusted for a 2 or more pixel width line, by tweaking the Textblock Width, Border Margin and ColumnDefinition Width. You can make the mouse grab ridiculously huge but the problem is that the increase is only on the left side; it's not centred on the line, which becomes more noticeable the more you increase it. But for a narrow line, it's an easy way to increase the mouse grab to something useable.

I'm using 2 pixel wide Gridsplitters and use a style to set IsMouseOver properties and such:

<Style TargetType="{x:Type GridSplitter}">
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="OpacityMask" Value="{StaticResource gs_OpacityMask}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type GridSplitter}">
                <Border Margin="-3,0" Background="Transparent">
                    <TextBlock x:Name="tb" Width="2"  Background="{TemplateBinding Background}" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" TargetName="tb" Value="#FF0B75FD" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

IMPORTANT: The ColumnDefinition Width needs to be set to 3 or 4 in this case of a 2 pixel width line.

like image 42
poby Avatar answered Nov 12 '22 09:11

poby


I wasn't able to get John Bowen's solution to work. It looked like it worked, but it seemed like the splitter only had 1 pixel of grab space.

I ended up doing this:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Stackpanel Grid.Row="0"/>
    <GridSplitter
        Grid.Row="1"
        HorizontalAlignment="Stretch"
        BorderBrush="DarkGray"
        Height="6"
        Background="Transparent"
        BorderThickness="0,1,0,0"
        Margin="0,0,0,-4"/>
    <Stackpanel Grid.Row="2"/>
</Grid>

This gives the splitter 6 pixels of height, but shows only the 1 pixel top border line. You use a negative bottom margin of ((Height / 2) - 1) in order to center that top margin line in the middle of the row.

The Background is Transparent otherwise you will see 6 pixels of gray or w/e the default color is. If you dig into the control template for GridSplitter with Blend you find out it's just a styled Rectangle with a Border or something like that.

like image 34
CodeOtaku Avatar answered Nov 12 '22 11:11

CodeOtaku