【问题标题】:Negative-margin control get clipped when resizing the window in WPF在 WPF 中调整窗口大小时,负边距控件被剪裁
【发布时间】:2016-10-27 20:29:09
【问题描述】:

我试图理解为什么在减小主窗口的宽度时边框元素会被剪裁。 请看下面的代码块。

    <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>

这是边框在原始窗口宽度中的显示:

未调整大小的窗口

正如您所见,由于上边距为负,在本例中为 -100,因此边框显示在其容器之外。这是我期望的边界。但是,当我减小主窗口宽度以到达红色矩形的右边缘时,边框的外部部分会被剪掉。

调整大小的窗口

我尝试将此边框元素放在自定义 StackPanel 中,该 StackPanel 覆盖了 ArrangeOverride、MeasureOverride 和 GetLayoutClip 方法,但不幸的是,在调整主窗口大小时不会调用这些方法。

如果有人可以向我解释原因是什么以及如何解决此问题,我将不胜感激。 非常感谢。

【问题讨论】:

    标签: wpf resize margin negative-number clipped


    【解决方案1】:

    根据@Marks 的解释,这是我的解决方案

    1. 创建自定义网格并覆盖 MeasureOverride 方法
    2. 用这个自定义网格替换内部网格

    自定义网格类

    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>
    

    【讨论】:

      【解决方案2】:
      1. 您将蓝色边框的Width 绑定到主窗口的Width。 未来:如果您想绑定到任何FrameworkElement 的宽度,请绑定到其ActualWidth 属性。

      2. WPF 绘制内容的顺序完全取决于包含控件。我会说在您的情况下,外部Grid 按定义的顺序绘制其需要更新的子。因此,只要内部网格随边界变化,您就可以继续使用。只要第三列的Width 发生变化,就是这种情况。一旦它为 0,就没有更多的变化,所以它不会得到更新。

      3. (2) 是推测 =)

      4. 不要做(1),没必要

      5. 使用一个网格

      一些 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>
      

      【讨论】:

      • 感谢马库斯的解释。 1. 这只是我的例子。我只是希望边框的主窗口宽度为 2。是的。我可以看到重点。我试图创建一个自定义网格来覆盖上面提到的 3 种方法,并在调整窗口大小时调用它们。 3. :) 4. 感谢您的建议 5. 我的实际应用问题是在我的示例中。我们需要有 2 个网格。当我的意思是内部网格是用户控件的容器时,我会根据您在第 2 点的解释找到解决方法。
      猜你喜欢
      • 2016-01-10
      • 2011-08-20
      • 2017-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多