Окно WPF - разрешить только горизонтальное изменение размера - PullRequest
15 голосов
/ 23 июня 2010

Я хочу разрешить горизонтальное изменение размера окна WPF. Как лучше всего этого добиться?

Ответы [ 8 ]

29 голосов
/ 15 мая 2012

Если вы хотите использовать подходы MinHeight и MaxHeight, но при этом разрешить автоматическому изменению размера окна в соответствии с размером его содержимого:

<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;
}
26 голосов
/ 24 июня 2010

Если вы установите атрибуты MinHeight и MaxHeight окна на желаемую высоту, окно будет иметь фиксированную высоту

3 голосов
/ 23 июня 2010

Это какая-то боль.По сути, вам нужно настроить функцию подключения для обработки сообщений Windows.Затем вы бы поймали сообщение WM_SIZING (0x0214) и изменили параметры так, чтобы горизонтальный размер не мог быть изменен.

Пит Браун также имеет некоторую полезную информацию оэта тема в его блоге.

1 голос
/ 30 ноября 2016

Следующее решение позволяет оставить SizeToContent без изменений,
не требует Win32 Interop или кода в вашем окне:

Он полагается на Реактивные расширения

В 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
Вы можете легко изменить код, чтобы разрешить обратное, или добавить свойства
чтобы сделать его настраиваемым.

1 голос
/ 23 июня 2010

Вы можете попробовать привязать данные к размеру окна, а затем установить размер обратно на старое значение при каждом изменении вертикального размера.

0 голосов
/ 17 января 2019

Опираясь на ответы от 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>
0 голосов
/ 24 мая 2016

Если у вас есть следующие требования: * Ширина может быть изменена пользователем (ResizeMode = CanResize) * Высота автоматически измеряется (SizeToContent = Высота)

Это не будет работать по двум причинам: * нетResizeMode = CanResizeHeight *, когда пользователь изменяет размер окна, он будет увеличивать SizeToContent до «Manual»

Простой взлом, который я использую, заключается в том, чтобы постоянно принудительно возвращать «SizeToContent» обратно к желаемому значению.1007 * Вы также можете использовать событие ContentRendered.Событие PropertyChanged не будет работать.Это не идеально, поскольку пользователь все еще может перемещать курсор по вертикали, и это вызовет некоторое мерцание, если сделать это быстро.

0 голосов
/ 29 января 2015

Если вы хотите использовать подходы MinHeight и MaxHeight, но при этом разрешаете автоматически изменять размер окна в соответствии с размером его содержимого:

Чтобы разрешить автоматическое определение размера контента, не используйте событие Loaded. Вместо этого используйте событие ContentRendered.

...