locked
Get a views actual height and width RRS feed

  • Question

  • I have a view that has a viewmodel as its datacontext, The question I have is that I need to know the height and width of the view, trying to do mvvm. What is the best way to let the viewmodel know the Height and Width of a view?

    Is multibinding using a converter the best way or is there another?

    Cheers Mike

    Wednesday, March 9, 2011 9:27 AM

Answers

  • Hello,

     

    The solution proposed by Muhammad will get the value of Width and Height properties but I think that you need the ActualWidth and ActualHeight values.

    But you can't bind these properties with the ViewModel in XAML because they are readonly.

    So, to do it in the MVVM way you need to create two attached properties to get the ActualWidth and ActualHeight and then bind the ViewModel to these properties

     

    Good Luck.

    • Proposed as answer by Sheldon _Xiao Friday, March 11, 2011 5:31 AM
    • Marked as answer by surfluds Friday, March 11, 2011 6:02 PM
    Thursday, March 10, 2011 12:46 AM

All replies

  • Hi Mike,

    If you are working with MVVM then normally your view should have a property called Model which is nothing more then a getter and setter for the datacontext. On this model you can create as many properties as you want and you can either bind to them in Xaml or in the code behind.

    public MyViewModel Model
    {
       get{return DataContext as MyViewModel;}
       set { DataContext = value; }
    }
    
    

    Regards,

    Annihil8
    Wednesday, March 9, 2011 9:35 AM
  • Thanks for replying Annihil8 I am not quite sure I get you, the view has a Height and width but as I understand the viewmodel should know nothing of the view, so how can it get the views Height and Width properties, I learn better by example and can find no links to similar questions.

    Regards mike

    Wednesday, March 9, 2011 7:48 PM
  • Hi surfluds,

    You can create properties ViewHeight and ViewWidth in view model. Keep it public. Now simply bind those properties to Height and Width.

    <Window ...
       Height="{Binding ViewHeight , Mode=OneWayToSource}"
       Width ="{Binding ViewWidth , Mode=OneWayToSource}">
    ...
    </Window>

    Thanks,
    Muhammad
    http://shujaatsiddiqi.blogspot.com/


    Muhammad Siddiqi
    • Proposed as answer by Sheldon _Xiao Friday, March 11, 2011 5:31 AM
    Wednesday, March 9, 2011 10:01 PM
  • Well Muhammad has added the extra info :)
    You set his properties on my example viewmodel and you have your width and heigth available.
    Don't forget to implement the OnNotifyChanged event in the setters!

    Regards,
    Annihil8
    Wednesday, March 9, 2011 11:36 PM
  • Hello,

     

    The solution proposed by Muhammad will get the value of Width and Height properties but I think that you need the ActualWidth and ActualHeight values.

    But you can't bind these properties with the ViewModel in XAML because they are readonly.

    So, to do it in the MVVM way you need to create two attached properties to get the ActualWidth and ActualHeight and then bind the ViewModel to these properties

     

    Good Luck.

    • Proposed as answer by Sheldon _Xiao Friday, March 11, 2011 5:31 AM
    • Marked as answer by surfluds Friday, March 11, 2011 6:02 PM
    Thursday, March 10, 2011 12:46 AM
  • Hi surfluds,

    Have you got what you need?

     

    Best regards,


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, March 11, 2011 5:31 AM
  • Have just got up and started my day, will test out and let you know, but the replies do make sense to me so hopefully.
    Friday, March 11, 2011 8:07 AM
  • Hello,

    Here you have a behavior with the ActualWidth attached property:

     

     public class WindowBehaviors
        {

            public static double GetActualWidth(DependencyObject obj)
            {
                return (double)obj.GetValue(ActualWidthProperty);
            }

            public static void SetActualWidth(DependencyObject obj, double value)
            {
                obj.SetValue(ActualWidthProperty, value);
            }

            public static readonly DependencyProperty ActualWidthProperty =
                DependencyProperty.RegisterAttached("ActualWidth", typeof(double), typeof(WindowBehaviors), new FrameworkPropertyMetadata(double.NaN, new PropertyChangedCallback(ActualWidthChanged)) { BindsTwoWayByDefault = true });


            private static void ActualWidthChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
            {
                Window w = source as Window;
                if (w != null)
                {
                    w.SizeChanged += (se, ev) =>
                    {
                        SetActualWidth((DependencyObject)se,ev.NewSize.Width);
                    };
                }
            }
        }

     

    Then you can use it in xaml in the following way:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:bhv="clr-namespace:WpfApplication1"<!-- you behavior namespace -->
            Title="MainWindow"
            bhv:WindowBehaviors.ActualWidth="{Binding WindowWidth}">
       
        <Grid>
            <TextBlock Text="{Binding WindowWidth}"></TextBlock><!-- If you resize the window the textblock will show the actual width  -->
        </Grid>
    </Window>

    In the example, the WindowWidth property is declared in the window's code behind and implements property change notification

            private double windowWidth;
         
            public MainWindow()
            {
                this.DataContext = this;
            }

            public double WindowWidth
            {
                get {return windowWidth;}
                set {
                    windowWidth = value;
                    NotifyPropertyChange("WindowWidth");
                }
            }

    Good Luck

     

     

    Friday, March 11, 2011 11:46 AM
  • Hi Homero, thanks for that reply, very informative. I have on equery about it, If I have a Mainwindow and a MainWindowViewModel if I am not mistaken this will allow the viewmodel to get the MainWindows actualwidth by the fact that it is an attached property.

    Are attached properties another thing to learn how to use correctly (they seem usefull)?

    Thanks Mike

    Friday, March 11, 2011 2:24 PM
  • Hello,

    The behaviors play an important role in MVVM pattern and they are made of attached properties.

    A behavior, among other things, avoids you to write code behind and helps to maintain the separation between the view and the viewmodel.

    There are a lot of advantages in using attached behaviors.

    If you want to learn more about attached behaviors you can read the following link:

     

    http://joshsmithonwpf.wordpress.com/2008/08/30/introduction-to-attached-behaviors/

     

    Hope it helps.

    Friday, March 11, 2011 2:51 PM
  • Excellent help as usual everyone, thats made it all a lot clearer.
    Friday, March 11, 2011 6:03 PM