2
votes

I have defined my GridSplittler XAML like the following.

<Window>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
    </Grid>

    <Border Grid.Column="0" Background="Red" />
    <GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="3" Height="Auto" HorizontalAlighment="Stretch" VerticalAlignment="Stretch" />
    <Border Grid.Column="0" Background="Green" />

</Window>

This will create two columns with a grid splitter between them and it will correctly resize the columns as the grid splitter is dragged left and right. Now if you resize the whole Window I would like the width of left red column to remain fixed and have the width of the right green column change (as the Window is resized). Its the same effect as when you resize the whole Visual Studio application and the Solution Explorer width remains fixed but the width of a code tab changes. Also the same as the SQL Server Management Studio; the Object Explorer width remains fixed but the SQL tabs width changes. I realize that these two examples use a more complicated docking control but I was hoping to achieve the same result with using the WPF GridSplitter.

Edit: Based on mathieu suggestions all the was necessary was to give the first column definition an initial width (shown using 200 below).

<Grid Name="GridName">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Border Grid.Column="0" Background="Red" />
    <GridSplitter Name="SplitterName" Grid.Column="1" ResizeDirection="Columns" Width="3" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    <Border Grid.Column="2" Background="Green" />
</Grid>

Now when the Window is re-sized it only changes the width of the green border and the width of the red border remains fixed. Thanks!

2

2 Answers

1
votes

If you don't mind some code behind, you can achieve this behaviour by reacting to the DragDelta event of the splitter, and adjusting the width of the first column, by removing the Star width, and fixing the width according to the drag delta.

Xaml :

<Grid Name="GridName">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Border Grid.Column="0" Background="Red" />
    <GridSplitter Name="SplitterName" Grid.Column="1" ResizeDirection="Columns" Width="3" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    <Border Grid.Column="2" Background="Green" />
</Grid>

Code behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        SplitterName.DragDelta += SplitterNameDragDelta;
    }

    private void SplitterNameDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        GridName.ColumnDefinitions[0].Width = new GridLength(GridName.ColumnDefinitions[0].ActualWidth + e.HorizontalChange);
    }
}
0
votes

I've used the snipet of mathieu - and modified it for code behind use. In my case I need a dynamic number of Items resized by the GridSplitter.

I used the Thumb Control to have full control of the action

private Thumb GetNewThumbAsGridSplitter(int column)
    {
        var gs = new Thumb();
        gs.SetValue(Grid.ColumnProperty, column);
        // gs.SetValue(Grid.RowSpanProperty, 2);
        // gs.SetValue(Grid.RowProperty, 1);
        gs.Width = 5;
        gs.MouseEnter += (o, i) =>
        {
            Mouse.OverrideCursor = Cursors.ScrollWE;
        };
        gs.MouseLeave += (o, i) =>
        {
            Mouse.OverrideCursor = Cursors.Arrow;
        };
        gs.DragDelta += (o, i) =>
        {
            var grid = (Grid)gs.Parent;
            var previous = (YourControl)((grid.Children[column - 1]));
            var next = (YourControl)(grid.Children[column + 1]);

            if (next.MinWidth >= (next.ActualWidth - i.HorizontalChange))
            {
                return;
            }

            if (previous.MinWidth >= (previous.ActualWidth + i.HorizontalChange))
            {
                return;
            }

            previous.Width = previous.ActualWidth + i.HorizontalChange;
            next.Width = next.ActualWidth - i.HorizontalChange;
        };

        return gs;
    }