多个自动列定义导致GridSplitter行为异常。

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>

当只有一个ColumnDefinitionWidthAuto时,GridSplitter正常工作。然而,一旦有多个WidthAuto的列时,在移动GridSplitter时第一个Auto列也会被调整大小(可以在单元格1,0中看到)。
调整前:

enter image description here

调整后:

enter image description here

如何防止GridSplitter调整第二列的大小?

想要的行为是什么?调整 0,03,0 列的大小吗? - ASh
@ASh 是的,完全正确。 - Zev Spitz
我猜一个GridSplitter默认情况下无法实现。如果你看一下ResizeBehavior属性,也没有这个选项。 - Mighty Badaboom
@MightyBadaboom,“ResizeBehavior”的各种设置似乎没有任何效果。 - Zev Spitz
3个回答

6
如果您无法修改现有列,也许可以尝试通过编程来实现此行为...
给列命名:
<Grid.ColumnDefinitions>
    <ColumnDefinition Name="firstColumn" Width="*" />
    <ColumnDefinition Name="secondColumn" Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

向网格分隔器添加事件:

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

在拖动分隔条之前保存列宽,然后将更改应用于第一列宽度而不是第二列:

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

我不一定需要名称;我可以从“ColumnDefinitions”集合中访问网格列。 - Zev Spitz
当然,我只是在示例中为了清晰起见给它们命名的。 - Nemanja Banda

2
我会修改布局以确保GridSplitter与相邻的网格列配合使用:
<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>

我认为这应该可以工作,但我不能使用它,因为我正在尝试将内容注入到WPF数据网格中,并且不能轻松修改现有的列。 - Zev Spitz

1
我一直在进行测试,我相信我可以解释发生了什么,即使我不完全确定如何修复它。
测试: 移动分隔符并观察(0,0)和(3,0)的相对大小。它们始终完全相等。
结论:这种行为是因为(0,0)和(3,0)都是*宽度,因此它们每个都有一半的可用宽度。然而,分隔符限制了(3,0)的大小。由于(3,0)有一个大小限制,但也应该有一半的可用宽度,这意味着(0,0)也具有与(3,0)相同的大小限制。当分隔符强制(3,0)缩小时,(0,0)必须缩小以保持由*宽度指定的比例。因此,(1,0)和(2,0)是唯一允许增长以填充剩余空间的列,而由于(2,0)仅包含带有静态宽度20的分隔符,所以(1,0)增长以填充剩余空间。
正如我所说的,我不确定如何解决这个问题,但解决问题的第一步是理解它。希望这能帮助某人发现解决方案。
编辑:进一步测试表明,上述情况仅在将(1,0)设置为自动或固定宽度时才成立。如果(1,0)设置为*或*的某个倍数,则所有*部分似乎都表现出奇怪的行为,并且会随意增长和缩小,而不考虑它们的比例。
编辑2:在寻找过程中,我遇到了这个链接:https://wpf.2000things.com/tag/gridsplitter/ 该链接提到的其中一件事是:
引用: 请记住,如果将GridSplitter放置在其自己的列中并将其HorizontalAlignment设置为Center,则会调整其两侧的列大小。在下面的示例中,调整列0和列2的宽度,但不更改列3的宽度。

在我的测试中观察到的所有行为都符合该链接中提到的示例之一,因此我的新结论是这种行为都是故意的,而不是像我一直认为的奇怪的错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接