Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with binding to Window Height and Width

I have some problems when I try to bind the height and width of a window to properties in my view model. Here is a small sample app to illustrate the problem. This is the code in app.xaml.xs

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
       base.OnStartup(e);
        MainWindow mainWindow = new MainWindow();
        MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
        mainWindow.DataContext = mainWindowViewModel;
        mainWindow.Show();
    }
}

This is MainWindow.xaml:

<Window x:Class="TestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="{Binding WindowHeight}" 
        Width="{Binding WindowWidth}"
        BorderThickness="{Binding WindowBorderThickness}">
</Window>

And this is the view model:

public class MainWindowViewModel
{
    public int WindowWidth { get { return 100; } }
    public int WindowHeight { get { return 200; } }
    public int WindowBorderThickness { get { return 8; } }
}

When the program is started the getters of WindowHeight and WindowBorderThickness (but not WindowWidth) are called, so the height and the border of the window is set properly, but not the width.

I then add button that will trigger PropertyChanged for all properties, so that the view model now looks like this:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void TriggerPropertyChanges()
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("WindowWidth"));
            PropertyChanged(this, new PropertyChangedEventArgs("WindowHeight"));
            PropertyChanged(this, new PropertyChangedEventArgs("WindowBorderThickness"));
        }

    }

    public ICommand ButtonCommand { get { return new RelayCommand(delegate { TriggerPropertyChanges(); }); } }

    public int WindowWidth { get { return 100; } }
    public int WindowHeight { get { return 200; } }
    public int WindowBorderThickness { get { return 8; } }
}

Now, when I click the button, the getter of WindowBorderThickness is called, but not the ones for WindowWidth and WindowHeight. It all just seems very weird and inconsistent to me. What am I missing?

like image 959
D.H. Avatar asked Apr 20 '10 08:04

D.H.


3 Answers

Try using two way binding, it worked for me:

Width="{Binding Path=xExt, Mode=TwoWay}"
like image 139
Gregory Seront Avatar answered Nov 04 '22 18:11

Gregory Seront


I will try to answer my own question. The bindings are working, but we can't really be sure that the layout system asks for e.g. the Width property of the window.

From MSDN:

If this element is a child element within some other element, then setting this property to a value is really only a suggested value. The layout system as well as the particular layout logic of the parent element will use the value as a nonbinding input during the layout process. In practical terms, a FrameworkElement is almost always the child element of something else; even when you set the Height on Window. (For Window, that value is used when the underlying application model establishes the basic rendering assumptions that create the Hwnd that hosts the application.)

A solution that seems to work is to bind the WindowWidth property to MinWidth and MaxWidth, as well as Width. One of these will be retrieved, at least in the test scenario I was using above.

like image 31
D.H. Avatar answered Nov 04 '22 17:11

D.H.


I had the same problem and I noticed that it depends whether height or width is written first in xaml. If height is first, then Binding work only for it and vice versa. The solution was to set Binding mode to 'TwoWay': The project I have made was with MS Studio 2010 and .NET 4.0

like image 12
VNedyalkov Avatar answered Nov 04 '22 17:11

VNedyalkov