WPF Binding window height to ViewModel property

2019-09-02 18:54发布

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.

标签: c# wpf mvvm
1条回答
Animai°情兽
2楼-- · 2019-09-02 19:46

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")
查看更多
登录 后发表回答