I want to only allow my WPF window to be resized horizontally. How best can I achieve this?
-
Wow, I thought setting MinHeight, Height and MaxHeight to the same value works but it doesn't. Nice to know. – DHN Jun 23 '10 at 07:02
8 Answers
If you want to use the MinHeight
and MaxHeight
approach but still allow the window to automatically size itself to fit the size of its content:
<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">
In code-behind:
private void window_Loaded(object sender, RoutedEventArgs e)
{
this.MinWidth = this.ActualWidth;
this.MinHeight = this.ActualHeight;
this.MaxHeight = this.ActualHeight;
}

- 530
- 5
- 10
-
1Just as Tim Richards recommends, I had to move setting the `MinHeight` and `MaxHeight` properties to the `ContentRendered` event after noticing the bottom border of a `TextBox` and `Button` were being clipped in a `Grid` contained within a `GroupBox`. – Major Malfunction Jun 26 '17 at 07:36
-
3And this doesn't help if the window contents change and the window size has to follow dynamically – floydheld Oct 10 '19 at 13:09
If you set the MinHeight
and MaxHeight
attributes of the window to the desired height the window will have a fixed height

- 101,612
- 66
- 270
- 352

- 296
- 2
- 2
-
-
21Unfortunately incompatible with automatic height calculation based on content size. – Roman Starkov Mar 28 '12 at 22:06
It's kind of a pain. Basically you need to set up a hook function to process windows messages. Then you would catch the WM_SIZING (0x0214) message and modify the parameters so that the horizontal dimension could not be changed.
Pete Brown also has some great info on this topic on his blog.

- 68,005
- 14
- 144
- 156
You could try databinding to the size of the window, and then setting the size back to the old value whenever the vertical dimension is changed.

- 17,233
- 9
- 65
- 88
-
-
True. But in most cases I suspect it will be fast enough that the user doesn't notice. – Daniel Rose Jun 23 '10 at 10:55
If you have the following requirements: * Width can be user resized (ResizeMode=CanResize) * Height is automatically sized (SizeToContent=Height)
It won't work for two reasons: * there is no ResizeMode=CanResizeHeight * when the user resizes the window, it will clobber SizeToContent to "Manual"
A simple hack I use is to constantly force "SizeToContent" back to my desired value.
<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;
}
You can also use the ContentRendered event. The PropertyChanged event won't work. This isn't perfect, since the user can still move the cursor vertically, and it will cause some flickering if done quickly.

- 585
- 2
- 6
- 17
The following solution allows you to leave SizeToContent
intact,
doesn't require Win32 Interop
or code behind in your Window:
It does rely on Reactive Extensions
In the Package Manager
run:
Install-Package System.Reactive
Then you start by creating a new 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;
});
}
}
Then you add a UIElement
at the bottom of your Window and apply the Behavior
:
<Border Background="Gray"
Height="10"
Cursor="SizeNS"
Grid.ColumnSpan="2">
<i:Interaction.Behaviors>
<b:VerticalResizeWindowBehavior MinHeight="600"/>
</i:Interaction.Behaviors>
</Border>
Set the following Properties on your Window:
ResizeMode="NoResize"
SizeToContent="Width"
Note: In this example, the user is allowed to resize Vertically
but not Horizontally
You can easily change the code to allow the opposite, or add properties
to make it configurable.

- 21,178
- 26
- 94
- 142
If you want to use the MinHeight and MaxHeight approach but still allow the window to automatically size itself to fit the size of its content:
To allow automatic content sizing don't use the Loaded event. Use the ContentRendered event instead.
Building on the answers from User3810621 and others, this can be turned into a reusable behavior which locks in the calculated sizes as min and/or max after the first content render:
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
}
}
The remaining, repetitive values are trivial and omitted for brevity.
Usage:
<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>

- 22,897
- 2
- 80
- 94