【问题标题】:WPF Window - Only allow horizontal resizeWPF 窗口 - 只允许水平调整大小
【发布时间】:2011-03-07 04:13:15
【问题描述】:

我只想让我的 WPF 窗口水平调整大小。 我怎样才能最好地做到这一点?

【问题讨论】:

  • 哇,我认为将 MinHeight、Height 和 MaxHeight 设置为相同的值是可行的,但事实并非如此。很高兴知道。

标签: wpf resize window


【解决方案1】:

这有点痛苦。基本上你需要设置一个钩子函数来处理windows消息。然后您将捕获WM_SIZING (0x0214) 消息并修改参数以使水平尺寸无法更改。

Pete Brown 在他的博客上也有关于这个主题的一些重要信息。

【讨论】:

    【解决方案2】:

    您可以尝试将数据绑定到窗口的大小,然后在垂直尺寸发生变化时将大小设置回旧值。

    【讨论】:

    • 唯一的缺点就是后期处理。
    • 是的。但在大多数情况下,我怀疑它会足够快以至于用户不会注意到。
    【解决方案3】:

    如果您将窗口的MinHeightMaxHeight 属性设置为所需的高度,则窗口将具有固定高度

    【讨论】:

    • 工作是一种享受......当你想到它时是如此明显。谢谢
    • 很遗憾与基于内容大小的自动高度计算不兼容。
    【解决方案4】:

    如果您想使用MinHeightMaxHeight 方法但仍允许窗口自动调整大小以适应其内容的大小:

    <Window x:Class="MyWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            SizeToContent="WidthAndHeight"
            ResizeMode="CanResize"
            Loaded="window_Loaded">
    

    在代码隐藏中:

    private void window_Loaded(object sender, RoutedEventArgs e)
    {
        this.MinWidth = this.ActualWidth;
        this.MinHeight = this.ActualHeight;
        this.MaxHeight = this.ActualHeight;
    }
    

    【讨论】:

    • 正如 Tim Richards 建议的那样,在注意到 TextBoxButton 的底部边框被设置后,我不得不将 MinHeightMaxHeight 属性设置为 ContentRendered 事件剪辑在 Grid 中包含在 GroupBox 中。
    • 如果窗口内容发生变化并且窗口大小必须动态变化,这将无济于事
    【解决方案5】:

    如果您想使用 MinHeight 和 MaxHeight 方法但仍允许窗口自动调整大小以适应其内容的大小:

    要允许自动调整内容大小,请不要使用 Loaded 事件。请改用 ContentRendered 事件。

    【讨论】:

    • 你能粘贴这句话的来源吗?
    【解决方案6】:

    如果您有以下要求: * 宽度可以由用户调整(ResizeMode=CanResize) * 高度自动调整大小(SizeToContent=Height)

    它不起作用有两个原因: * 没有 ResizeMode=CanResizeHeight * 当用户调整窗口大小时,它会将 SizeToContent 更改为“手动”

    我使用的一个简单技巧是不断强制“SizeToContent”回到我想要的值。

    <Window x:Class="MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        SizeToContent="Height"
        ResizeMode="CanResize"
        LayoutUpdated="LayoutUpdated">
    
    private void LayoutUpdated(object sender, EventArgs e)
    {
        SizeToContent = SizeToContent.Height;
    }
    

    您也可以使用 ContentRendered 事件。 PropertyChanged 事件将不起作用。这并不完美,因为用户仍然可以垂直移动光标,如果快速完成会导致一些闪烁。

    【讨论】:

      【解决方案7】:

      以下解决方案可以让您保持SizeToContent不变,
      不需要Win32 Interop 或窗口中的代码:

      它确实依赖于Reactive Extensions

      Package Manager 运行:

      Install-Package System.Reactive
      

      然后你开始创建一个新的Behavior

      public class VerticalResizeWindowBehavior : Behavior<UIElement>
      {
          public static readonly DependencyProperty MinHeightProperty = DependencyProperty.Register("MinHeight", typeof(double), typeof(VerticalResizeWindowBehavior), new PropertyMetadata(600.0));
          public double MinHeight
          {
              get { return (double)GetValue(MinHeightProperty); }
              set { SetValue(MinHeightProperty, value); }
          }
      
          protected override void OnAttached()
          {
              base.OnAttached();
      
              var window = Window.GetWindow(AssociatedObject);
              var mouseDown = Observable.FromEventPattern<MouseButtonEventArgs>(AssociatedObject, "MouseLeftButtonDown")
                                          .Select(e => e.EventArgs.GetPosition(AssociatedObject));
      
              var mouseUp = Observable.FromEventPattern<MouseButtonEventArgs>(AssociatedObject, "MouseLeftButtonUp")
                                      .Select(e => e.EventArgs.GetPosition(AssociatedObject));
      
              var mouseMove = Observable.FromEventPattern<MouseEventArgs>(AssociatedObject, "MouseMove")
                                          .Select(e => e.EventArgs.GetPosition(AssociatedObject));
      
              var q = from start in mouseDown
                      from position in mouseMove.TakeUntil(mouseUp)
                      select new { X = position.X - start.X, Y = position.Y - start.Y };
      
              mouseDown.Subscribe(v => AssociatedObject.CaptureMouse());
              mouseUp.Subscribe(v => AssociatedObject.ReleaseMouseCapture());
      
              q.ObserveOnDispatcher().Subscribe(v =>
              {
                  var newHeight = window.Height + v.Y;
                  window.Height = newHeight < MinHeight ? MinHeight : newHeight;                
              });
          }
      }
      

      然后在窗口底部添加UIElement 并应用Behavior

      <Border Background="Gray" 
              Height="10" 
              Cursor="SizeNS"
              Grid.ColumnSpan="2">
          <i:Interaction.Behaviors>
              <b:VerticalResizeWindowBehavior MinHeight="600"/>
          </i:Interaction.Behaviors>
      </Border>
      

      在您的窗口上设置以下属性:

      ResizeMode="NoResize"
      SizeToContent="Width"
      

      注意:在这个例子中,用户可以调整Vertically的大小,但不能调整Horizontally的大小
      您可以轻松更改代码以允许相反的情况,或添加属性
      使其可配置。

      【讨论】:

        【解决方案8】:

        基于 User3810621 和其他人的答案,这可以转化为可重用行为,在第一次内容渲染后将计算的大小锁定为最小和/或最大:

        namespace whatever.util.wpf.behaviors
        {
            using System.Windows;
            using System.Windows.Interactivity;
        
            public class LockInitialSize : Behavior<Window>
            {
                protected override void OnAttached()
                {
                    base.OnAttached();
                    AssociatedObject.ContentRendered += OnContentRendered;
                }
        
                protected override void OnDetaching()
                {
                    // possibly detached before ever rendering
                    AssociatedObject.ContentRendered -= OnContentRendered;
                    base.OnDetaching();
                }
        
                private void OnContentRendered(object s, EventArgs e)
                {
                    // Just once
                    AssociatedObject.ContentRendered -= OnContentRendered;
        
                    if (MinWidth)
                    {
                        AssociatedObject.MinWidth = AssociatedObject.ActualWidth;
                    }
                    /// ... MaxWidth, MinHeight, MaxHeight
                }
        
                #region MinWidth Property
        
                public bool MinWidth
                {
                    get => (bool)GetValue(MinWidthProperty);
                    set => SetValue(MinWidthProperty, value);
                }
        
                public static readonly DependencyProperty MinWidthProperty =
                    DependencyProperty.Register(nameof(MinWidth), typeof(bool), typeof(LockInitialSize));
        
                #endregion
        
                // ... MaxWidth, MinHeight, MaxHeight    
            }
        }
        

        其余的重复值是微不足道的,为简洁起见将其省略。

        用法:

        <Window ...
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:behaviors="clr-namespace:whatever.util.wpf.behaviors;assembly=whatever"
             SizeToContent="Height"
             ...>
            <i:Interaction.Behaviors>
                <behaviors:LockInitialSize MinHeight="True" MaxHeight="True" />
            </i:Interaction.Behaviors>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-15
          • 1970-01-01
          相关资源
          最近更新 更多