多个自动列定义导致奇怪的 GridSplitter 行为
Multiple Auto column definitions causing weird GridSplitter behavior
我有以下 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>
当只有一个ColumnDefinition
的Width
为Auto
时,GridSplitter
可以正常工作。但是,一旦有多个 Width
为 Auto
的列,第一个 Auto
列也会在移动 GridSplitter
时调整大小(可以在单元格 [=19 中看到) =]).
调整大小前:
调整大小后:
如何防止 GridSplitter 调整第二列的大小?
我会修改布局以确保 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>
如果您无法修改现有列,也许您可以尝试以编程方式实现此行为...
为列命名:
<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);
}
}
我一直在做一些测试,我相信我可以解释发生了什么,即使我不完全确定如何修复它。
测试:
四处移动拆分器并观察 (0,0) 和 (3,0) 的相对大小。它们总是完全相等的。
结论:这种行为是由于 (0,0) 和 (3,0) 都是 * 宽度,所以它们每个都有可用宽度的一半。但是,拆分器对 (3,0) 的大小设置了限制。由于 (3,0) 对其大小有限制,但也应该具有可用宽度的一半,这意味着 (0,0) 也具有与 (3,0) 相同的大小限制。由于拆分器强制 (3,0) 收缩,(0,0) 也必须收缩以保持 * 宽度指定的比例。因此 (1,0) 和 (2,0) 是唯一允许增长以填充剩余 space 的列,并且由于 (2,0) 仅包含静态宽度为 20 的拆分器, (1,0) 增长以填充剩余的 space.
正如我所说,我不确定如何解决这个问题,但解决问题的第一步是理解它。所以希望这会帮助别人找到解决方案。
编辑:进一步测试表明,只有当 (1,0) 设置为自动或固定宽度时,以上情况才成立。如果 (1,0) 设置为 * 或 * 的某个倍数,则所有 * 部分的行为似乎都很奇怪,并且在不考虑其假定比例的情况下增大和缩小。
EDIT2:环顾四周,我遇到了这个 link:https://wpf.2000things.com/tag/gridsplitter/
link 提到的其中一件事如下:
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.
我在测试中观察到的所有行为都符合 link 中提到的示例之一,所以我的新结论是这种行为都是故意的,而不是像我想象的那样是一个奇怪的错误沿着.
我有以下 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>
当只有一个ColumnDefinition
的Width
为Auto
时,GridSplitter
可以正常工作。但是,一旦有多个 Width
为 Auto
的列,第一个 Auto
列也会在移动 GridSplitter
时调整大小(可以在单元格 [=19 中看到) =]).
调整大小前:
调整大小后:
如何防止 GridSplitter 调整第二列的大小?
我会修改布局以确保 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>
如果您无法修改现有列,也许您可以尝试以编程方式实现此行为...
为列命名:
<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);
}
}
我一直在做一些测试,我相信我可以解释发生了什么,即使我不完全确定如何修复它。
测试: 四处移动拆分器并观察 (0,0) 和 (3,0) 的相对大小。它们总是完全相等的。
结论:这种行为是由于 (0,0) 和 (3,0) 都是 * 宽度,所以它们每个都有可用宽度的一半。但是,拆分器对 (3,0) 的大小设置了限制。由于 (3,0) 对其大小有限制,但也应该具有可用宽度的一半,这意味着 (0,0) 也具有与 (3,0) 相同的大小限制。由于拆分器强制 (3,0) 收缩,(0,0) 也必须收缩以保持 * 宽度指定的比例。因此 (1,0) 和 (2,0) 是唯一允许增长以填充剩余 space 的列,并且由于 (2,0) 仅包含静态宽度为 20 的拆分器, (1,0) 增长以填充剩余的 space.
正如我所说,我不确定如何解决这个问题,但解决问题的第一步是理解它。所以希望这会帮助别人找到解决方案。
编辑:进一步测试表明,只有当 (1,0) 设置为自动或固定宽度时,以上情况才成立。如果 (1,0) 设置为 * 或 * 的某个倍数,则所有 * 部分的行为似乎都很奇怪,并且在不考虑其假定比例的情况下增大和缩小。
EDIT2:环顾四周,我遇到了这个 link:https://wpf.2000things.com/tag/gridsplitter/
link 提到的其中一件事如下:
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.
我在测试中观察到的所有行为都符合 link 中提到的示例之一,所以我的新结论是这种行为都是故意的,而不是像我想象的那样是一个奇怪的错误沿着.