在 WPF 中调整 window 的大小时,负边距控件被截断
Negative-margin control get clipped when resizing the window in WPF
我试图理解为什么在减小主 window 的宽度时边框元素会被剪掉。
请看下面的代码块。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="500" Name="MainWin">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border Background="Blue" Grid.Row="0" BorderBrush="Black" Width="{Binding ElementName=MainWin, Path=Width}" />
<Grid Grid.Row="1" Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Background="Black">
<Border Background="White" Width="150" Height="150" BorderBrush="Black" BorderThickness="2"
Margin="0,-100,0,0">
<TextBlock Text="{Binding ElementName=MainWin, Path=Width}" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Background="Red" />
<StackPanel Grid.Column="2" Background="Yellow" />
</Grid>
</Grid>
</Window>
原来window出现的边框宽度是这样的:
未调整大小window
如您所见,由于顶部边距为负,因此边框显示在其容器外部,在本例中为 -100。这就是我期望的边界。但是,当我减小主要 window 宽度以到达红色矩形的右边缘时,边框的外侧部分会被剪掉。
调整大小window
我试图将此边框元素放置在自定义 StackPanel 中,该 StackPanel 覆盖了 ArrangeOverride、MeasureOverride 和 GetLayoutClip 方法,但不幸的是,在调整主要 window 大小时这些方法未被调用。
如果有人能向我解释原因以及如何解决此问题,我将不胜感激。
非常感谢。
您正在将蓝色边框的 Width
绑定到 MainWindow 的 Width
。
对于未来:如果你想绑定到任何 FrameworkElement
的宽度,绑定到它的 ActualWidth
属性.
WPF 绘制内容的顺序完全取决于包含的控件。我会说在你的情况下,外部 Grid
绘制它的 children 需要按照它们定义的顺序更新 。因此,只要内部网格随边框一起变化,您就可以开始了。只要第三列的Width
发生变化就是这样。一旦它为 0,就没有更多变化,因此它不会更新。
(2)是推测=)
不要做(1),没必要
使用一个网格
一些XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Background="Blue" BorderBrush="Black" Grid.ColumnSpan="3"/>
<StackPanel Grid.Column="0" Grid.Row="1" Background="Black" >
<Border Background="White" Width="150" Height="150" BorderBrush="Black" BorderThickness="2" Margin="0,-100,0,0">
<TextBlock Text="{Binding ElementName=MainWin, Path=ActualWidth}" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Background="Red" />
<StackPanel Grid.Column="2" Grid.Row="1" Background="Yellow" />
</Grid>
根据@Marks的解释,这是我的解决方案
- 创建自定义网格并覆盖 MeasureOverride 方法
- 用这个自定义网格替换内部网格
自定义网格class
public class CustomGrid : Grid
{
private double _originalHeight = 0;
protected override Size MeasureOverride(Size constraint)
{
Size? size = null;
if (constraint.Width <= 300)
{
size = new Size(constraint.Width, _originalHeight);
}
else
{
size = base.MeasureOverride(constraint);
_originalHeight = constraint.Height;
}
return size.Value;
}
}
XAML代码
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="300" Width="500" Name="MainWin">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border Background="Blue" Grid.Row="0" BorderBrush="Black" Width="{Binding ElementName=MainWin, Path=Width}" />
<wpfApplication1:CustomGrid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Background="Black">
<Border Background="White" Width="150" Height="150" BorderBrush="Black" BorderThickness="2"
Margin="0,-100,0,0">
<TextBlock Text="{Binding ElementName=MainWin, Path=Width}" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" />
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Background="Red" />
<StackPanel Grid.Column="2" Background="Yellow" />
</wpfApplication1:CustomGrid>
</Grid>
我试图理解为什么在减小主 window 的宽度时边框元素会被剪掉。 请看下面的代码块。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="500" Name="MainWin">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border Background="Blue" Grid.Row="0" BorderBrush="Black" Width="{Binding ElementName=MainWin, Path=Width}" />
<Grid Grid.Row="1" Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Background="Black">
<Border Background="White" Width="150" Height="150" BorderBrush="Black" BorderThickness="2"
Margin="0,-100,0,0">
<TextBlock Text="{Binding ElementName=MainWin, Path=Width}" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Background="Red" />
<StackPanel Grid.Column="2" Background="Yellow" />
</Grid>
</Grid>
</Window>
原来window出现的边框宽度是这样的:
未调整大小window
如您所见,由于顶部边距为负,因此边框显示在其容器外部,在本例中为 -100。这就是我期望的边界。但是,当我减小主要 window 宽度以到达红色矩形的右边缘时,边框的外侧部分会被剪掉。
调整大小window
我试图将此边框元素放置在自定义 StackPanel 中,该 StackPanel 覆盖了 ArrangeOverride、MeasureOverride 和 GetLayoutClip 方法,但不幸的是,在调整主要 window 大小时这些方法未被调用。
如果有人能向我解释原因以及如何解决此问题,我将不胜感激。 非常感谢。
您正在将蓝色边框的
Width
绑定到 MainWindow 的Width
。 对于未来:如果你想绑定到任何FrameworkElement
的宽度,绑定到它的ActualWidth
属性.WPF 绘制内容的顺序完全取决于包含的控件。我会说在你的情况下,外部
Grid
绘制它的 children 需要按照它们定义的顺序更新 。因此,只要内部网格随边框一起变化,您就可以开始了。只要第三列的Width
发生变化就是这样。一旦它为 0,就没有更多变化,因此它不会更新。(2)是推测=)
不要做(1),没必要
使用一个网格
一些XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Background="Blue" BorderBrush="Black" Grid.ColumnSpan="3"/>
<StackPanel Grid.Column="0" Grid.Row="1" Background="Black" >
<Border Background="White" Width="150" Height="150" BorderBrush="Black" BorderThickness="2" Margin="0,-100,0,0">
<TextBlock Text="{Binding ElementName=MainWin, Path=ActualWidth}" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Background="Red" />
<StackPanel Grid.Column="2" Grid.Row="1" Background="Yellow" />
</Grid>
根据@Marks的解释,这是我的解决方案
- 创建自定义网格并覆盖 MeasureOverride 方法
- 用这个自定义网格替换内部网格
自定义网格class
public class CustomGrid : Grid
{
private double _originalHeight = 0;
protected override Size MeasureOverride(Size constraint)
{
Size? size = null;
if (constraint.Width <= 300)
{
size = new Size(constraint.Width, _originalHeight);
}
else
{
size = base.MeasureOverride(constraint);
_originalHeight = constraint.Height;
}
return size.Value;
}
}
XAML代码
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="300" Width="500" Name="MainWin">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border Background="Blue" Grid.Row="0" BorderBrush="Black" Width="{Binding ElementName=MainWin, Path=Width}" />
<wpfApplication1:CustomGrid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Background="Black">
<Border Background="White" Width="150" Height="150" BorderBrush="Black" BorderThickness="2"
Margin="0,-100,0,0">
<TextBlock Text="{Binding ElementName=MainWin, Path=Width}" FontSize="14" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" />
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Background="Red" />
<StackPanel Grid.Column="2" Background="Yellow" />
</wpfApplication1:CustomGrid>
</Grid>