Multiple Auto column definitions causing weird GridSplitter behavior
Asked Answered
A

3

8

I have the following XAML:

<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock Text="0,0" Grid.Column="0" Background="Yellow" />
        <TextBlock Text="1,0" Grid.Column="1" Background="SkyBlue" />
        <GridSplitter Width="20" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Stretch" ShowsPreview="True" />
        <TextBlock Text="3,0" Grid.Column="3" Grid.Row="0" />
    </Grid>
</Window>

When there is only one ColumnDefinition with a Width of Auto, the GridSplitter works properly. However, once there are multiple columns with a Width of Auto, the first Auto column also gets resized when the GridSplitter is moved (can be seen in cell 1,0).

Before resize:

enter image description here

After resize:

enter image description here

How can I prevent the GridSplitter from resizing the second column?

Alejandrinaalejandro answered 6/3, 2017 at 12:32 Comment(4)
what is desired behavior? resize 0,0 and 3,0 columns?Still
@Still Yes; exactly.Alejandrinaalejandro
I guess it's not possible with a GridSplitter out of the box. If you would have a look at the ResizeBehavior property there is no option for this.Redeeming
@MightyBadaboom The various settings for ResizeBehavior don't seem to have any effect.Alejandrinaalejandro
P
6

If you cannot modify the existing columns, perhaps you could try to achieve this behavior programmatically...

Name the columns:

<Grid.ColumnDefinitions>
    <ColumnDefinition Name="firstColumn" Width="*" />
    <ColumnDefinition Name="secondColumn" Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

Add events to grid spliiter:

<GridSplitter Name="gridSplitter" DragStarted="gridSplitter_DragStarted" DragCompleted="gridSplitter_DragCompleted" />

Then just save the column widths before splitter drag and apply the change to the first column width, instead of second:

public partial class MainWindow : Window
{
    private double savedFirstColumnWidth;
    private double savedSecondColumnWidth;

    private void gridSplitter_DragStarted(object sender, DragStartedEventArgs e)
    {
        // Save the initial column width values
        savedFirstColumnWidth = firstColumn.ActualWidth;
        savedSecondColumnWidth = secondColumn.ActualWidth;
    }

    private void gridSplitter_DragCompleted(object sender, DragCompletedEventArgs e)
    {           
        double dragChange = e.HorizontalChange;

        // Change the width of the first column instead of second
        firstColumn.Width = new GridLength(savedFirstColumnWidth + dragChange);
        // Set the with of the second column to the value saved before the drag
        secondColumn.Width = new GridLength(savedSecondColumnWidth);
    }
}
Polio answered 9/3, 2017 at 11:52 Comment(2)
I don't necessarily need names; I can access the grid columns from the ColumnDefinitions collection.Alejandrinaalejandro
Of course, I just named them in the example for clarity.Polio
S
2

I would modify layout to make sure that GridSplitter is working with adjacent grid columns:

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

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

        <TextBlock Text="0,0" Grid.Column="0" Background="Yellow" />
        <TextBlock Text="1,0" Name="Txt" Grid.Column="1" Background="SkyBlue" />
    </Grid>

    <GridSplitter Width="20" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" ShowsPreview="True" />
    <TextBlock Text="3,0" Grid.Column="2" Grid.Row="0" />
</Grid>
Still answered 6/3, 2017 at 13:13 Comment(1)
I assume this would work, but I cannot use this because I am trying to inject content into the WPF datagrid, and cannot easily modify the existing columns.Alejandrinaalejandro
B
1

I have been doing some testing, and I believe that I can explain what is happening, even if I am not entirely sure how to fix it.

The test: Move the splitter around and watch the relative sizes of (0,0) and (3,0). They are always exactly equal.

Conclusion: This behavior is a result of the fact that both (0,0) and (3,0) are * width, so each of them has half the available width. However, the splitter places a limit on the size of (3,0). Since (3,0) has a limit to its size, but also is supposed to have half the available width, this means that (0,0) also has the same size limits as (3,0). As the splitter forces (3,0) to shrink, (0,0) must also shrink to maintain the proportion specified by the * width. As a result (1,0) and (2,0) are the only columns that are allowed to grow to fill the remaining space, and since (2,0) only contains the splitter with a static width of 20, (1,0) grows to fill the remaining space.

As I said, I am not sure how to fix this, but the first step to fixing a problem is understanding it. So hopefully this will help someone discover the solution.

EDIT: Further testing indicates that the above is only true if (1,0) is set to Auto or Fixed Width. If (1,0) is set to * or some multiple of *, then all of the * sections seem to behave oddly, and grow and shrink with no regard to their supposed proportions.

EDIT2: Looking around I came accross this link: https://wpf.2000things.com/tag/gridsplitter/

One of the things that is mentioned at that link is the following:

Recall that a GridSplitter in its own column and with its HorizontalAlignment set to Center will resize columns on either side of it. In the example below, columns 0 and 2 are resized, but the width of column 3 is not changed.

All of the observed behavior in my tests fits in with one of the examples mentioned at that link, so my new conclusion is that this behavior is all intentional, rather then a strange bug like I supposed all along.

Buenrostro answered 10/3, 2017 at 20:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.