0
votes

This question has been asked once before however it did not get a satisfactory answer...

I am following the MVVM design archetype and I would like to be able to change the width and height of the window. To do this I decided to create two properties in my ViewModel:

private int xWidth;
public int XWidth
{
   get { return xWidth; }
   set
   {
        xWidth = value;
        RaisePropertyChanged("XWidth");
   }
}

private int yHeight;
public int YHeight
{
   get { return yHeight; }
   set
   {
        yHeight = value;
        RaisePropertyChanged("YHeight");
   }
}

I then bound the height and width to those properties:

Height="{Binding YHeight}" Width="{Binding XWidth}">

Finally I created an method which changes those values:

private void HomeExecute()
{
     ShowMain = true;
     ShowSearch = false;
     YHeight = 350;
     XWidth = 525;
}

This however is not working. When the method executes the window doesn't change size.

I know that the View is bound correctly to the ViewModel as other bindings work.

I also know that the method is being run as the ShowMain property gets changed.

I had a hunch that it might need a converter of sorts as I am passing to the width and height properties an int however my research didn't lead to anything.

2
I think here is explanation: link. Try to bind to Max/Min Width/Height and set them. This will emulate setting normal Width/Height properties. - ext
try using TwowayBinding thats worked for me. - Dinesh balan
That's quite interesting, although it cannot be the only problem as I have tried it with MaxWidth and MaxHeight now and still no luck. I was stepping through the program (F11) and it never took me to the 'set' property code. Which would explain why the view inst getting notified - Ryan Searle
@Dineshbalan Just gave that a go, unfortunately it didn't work, sorry - Ryan Searle
Try with double value - Dinesh balan

2 Answers

2
votes

I'm not sure, why the binding does not work, maybe it has something to do with the fact, that window is not just regular control, but some kind of wrapper around WinAPI. However, you can still use good old code behind event-based approach, even without breaking MVVM separation of concerns.

I have written MVVM sample, that does not use xaml binding, but implements two-way binding using "plain eventhandlers":

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();

        DataContext = new MainWindowViewModel();

        Loaded += delegate
        {
            Height = ViewModel.YHeight;
            Width = ViewModel.XWidth;
            ViewModel.PropertyChanged += ViewModelOnPropertyChanged;
            SizeChanged += MainWindow_SizeChanged;
        };
        Unloaded += delegate
        {
            ViewModel.PropertyChanged -= ViewModelOnPropertyChanged;
            SizeChanged -= MainWindow_SizeChanged;
        };

    }

    public MainWindowViewModel ViewModel
    {
        get { return (MainWindowViewModel)DataContext; }
    }


    private void ViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "YHeight")
        {
            Height = ViewModel.YHeight;
        }
        if (e.PropertyName == "XWidth")
        {
            Width = ViewModel.XWidth;
        }
    }

    void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        ViewModel.XWidth = e.NewSize.Width;
        ViewModel.YHeight = e.NewSize.Height;
    }
}
  • If you need to reuse this behaviour, you can move all the logic to behavior implemented as attached property or custom blend behavior
  • I recommend you to raise PropertyChanged only when property value changed. e.g if (xWidth != value) OnPropertyChanged("XWidth")
0
votes

You could just add the binding mode "two way" to your height and width bindings. Just edit your XAML to look like this:

Height="{Binding YHeight, Mode=TwoWay}" Width="{Binding XWidth, Mode=TwoWay}">

That's it. You can now set the window size from your viewmodel.