Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Auto column definitions causing weird GridSplitter behavior

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?

like image 516
Zev Spitz Avatar asked Mar 06 '17 12:03

Zev Spitz


3 Answers

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);
    }
}
like image 72
Nemanja Banda Avatar answered Sep 22 '22 00:09

Nemanja Banda


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>
like image 45
ASh Avatar answered Sep 24 '22 00:09

ASh


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.

like image 34
Brandon Kramer Avatar answered Sep 25 '22 00:09

Brandon Kramer