WPF - Trying to set the MinHeight of resizeable window based on its initial height
Asked Answered
S

2

7

I am trying to set the MinHeight / MinWidth of a resizeable window based on its initial height (when SizeToContent="WidthAndHeight").

I have seen a couple of answers / solutions:

http://weblogs.asp.net/psheriff/archive/2010/01.aspx

Set form MinWidth and MinHeight based on child property

However:

  1. I am trying to use the MVVM pattern and would like to be able to achieve this in the xaml.

  2. I would also like to keep values such as MinHeight out of the ViewModel - I dont think they belong there as they tie a trivial part of the behaviour of the view to the viewmodel. This is something I would like to leave to the UX designer.

A solution I am struggling with is to use the following xaml / binding:

<Window
        ....
        x:Name="mainWindow"
        SizeToContent="WidthAndHeight" 
        ResizeMode="CanResizeWithGrip"
        MinHeight="{Binding ElementName=mainWindow, Mode=OneTime, Path=ActualHeight}"
>

I would hope that 'Mode=OneTime' would bind the MinHeight to the initial value of the windows height.

But it does not work..

Can someone please explain why? Is there a solution that meets my criteria?

Thanks,

Mark

Syndicate answered 6/1, 2011 at 11:17 Comment(0)
O
12

Your code:

<Window
        ....
        x:Name="mainWindow"
        SizeToContent="WidthAndHeight" 
        ResizeMode="CanResizeWithGrip"
        MinHeight="{Binding ElementName=mainWindow, Mode=OneTime, Path=ActualHeight}"
>

It will not work, because the default value of ActualHeight is zero, and by the time WPF framework resizes your window, it already have assigned MinHeight with the default value of ActualHeight which is zero!

First thing you can try is this: change Mode=OneTime to Mode=Default, so that WPF could update MinHeight when ActualHeight gets changed on resizing the window. If that works, then you'll be happy.

Otherwise, you've to handle the SizeChanged event, and in the handler you can update the MinHeight.

<Window
            ....
            x:Name="mainWindow"
            SizeToContent="WidthAndHeight" 
            ResizeMode="CanResizeWithGrip"
            SizeChanged="Window_SizeChanged"
 >

In the code-behind:

bool firstTime= true;
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
     FrameworkElement  element = sender as FrameworkElement;
     if ( firstTime)
     {
            element.MinHeight = e.NewSize.Height;
            firstTime= false;
     }
}

Hope it will solve your problem. Or atleast will give you some idea as to how to proceeed. If you want to fix the size of your window, then you can also set the MaxHeight in the Window_SizeChanged() handler.


XAML ONLY SOLUTION

<Window
        x:Name="mainWindow"
        SizeToContent="WidthAndHeight" 
        ResizeMode="CanResizeWithGrip"
 >
 <Window.Triggers>
 <EventTrigger RoutedEvent="SizeChanged">
    <BeginStoryboard>
      <Storyboard Storyboard.TargetName="mainWindow">
            <DoubleAnimation Storyboard.TargetProperty="MinHeight" 
                             To="{Binding ElementName=mainWindow, Path=ActualHeight}"/>
       </Storyboard>
    </BeginStoryboard>
 </EventTrigger>
 </Window.Triggers>
 <!---- other code goes here--->
 </Window>
Overwinter answered 6/1, 2011 at 11:37 Comment(9)
This does set the MinHeight to a non zero value. However, it always sets the MinHeight whenever the window is resized, which means the user can increase the size of the window but never decrease it. I am trying to set the MinHeight one time only - to its initial size as determinted by ' SizeToContent="WidthAndHeight" 'Syndicate
Maybe there is a way to defer the binding until the window has first resized. Can I do that in xaml?Syndicate
@Mark : You should handle the SizeChanged event :-)Overwinter
@Nawaz : Cheers, that would work, but I was trying to find a xaml only solution.Syndicate
@Mark : I've posted XAML Only Solution. Please try that. And let me know. I'm curious to know if that solves your problem. BTW, I tried that myself. It seems to working :-)Overwinter
+1, was just about to post a similar solution. I think you should change SizeChanged to Loaded thoughFurcate
@Meleak : let Mark experiment with Loaded event. If that works, that will be even better solution.Overwinter
Cheers both of you! XAML Only Solution works perfectly (with the RoutedEvent set to 'Loaded' rather than 'SizeChanged'). Very educational, Cheers :-)Syndicate
@Mark : there is still one thing which you didn't : upvote :POverwinter
D
1

I suspect you are looking for this piece of code:

<Window 
x:Name="myWindow" 
MinHeight="266" Height="{Binding ElementName=myWindow, Path=MinHeight}" 
MinWidth="480"  Width="{Binding ElementName=myWindow, Path=MinWidth}">

This sets the Height and Width to the MinHeight and MinWidth set. So you only have one position to change.

Damages answered 10/2, 2013 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.