Окно WPF - разрешает только горизонтальное изменение размера

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

Ответ 1

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

Ответ 2

Если вы хотите использовать подход 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;
}

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

В Package Manager run:

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

Ответ 6

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

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

Ответ 7

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

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

Простой хак, который я использую, заключается в том, чтобы постоянно принудительно "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 не будет работать. Это не идеально, так как пользователь может перемещать курсор по вертикали, и это приведет к некоторому мерцанию, если оно будет выполнено быстро.