简体   繁体   中英

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:

在此输入图像描述

After resize:

在此输入图像描述

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

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);
    }
}

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM