在MVVM场景下,控件绑定到View而不是ViewModel

本文关键字:View ViewModel 绑定 控件 MVVM | 更新日期: 2023-09-27 18:11:56

我已经使用MVVM模型一周左右了,我想我现在已经掌握了应该去哪里。注意这里的"think"

我有一个单一的ViewModel,我的视图(MainWindow)绑定到

_ViewModel = new MainViewModel();
this.DataContext = _ViewModel;

我有一些在ViewModel和随后的模型中工作的iccommands,我很好。

现在我从我的视图(主窗口)启动了几个窗口,这是我在代码隐藏中做的,因为它都是纯粹的视图相关的东西。我试图复制我在视图中的ViewModel中的iccommand设置,以简化我的生活,或者我认为。我设置了以下命令:

public ICommand comInitialiseWindows { get; private set; }
private bool _windowsactive = false;
public bool WindowsActive
{
    get { return _windowsactive; }
    set { SetProperty(ref _windowsactive, value); }
}
public bool comInitialiseWindows_CAN()
{
    return !_windowsactive;
}
private void comInitialiseWindows_DO()
{
    ... Code to do the window creation, etc.
}

我在MainWindow代码中有这个中继命令:

comInitialiseWindows = new RelayCommand(() => comInitialiseWindows_DO(), comInitialiseWindows_CAN);

如果我把它放在ViewModel中,它的工作原理除了窗口创建的东西,但作为它的视图相关我并不感到惊讶。

所以问题是当我点击按钮时代码不运行。我猜XAML是绑定到ViewModel的,但是如果不在代码隐藏中为每个按钮设置绑定到主窗口,我无法找到解决这个问题的方法。我原以为下面的代码可以工作,但它没有:

<Button x:Name="ribbutLayoutWindows"                                     
    Command="{Binding local:comInitialiseWindows}" 
    IsEnabled="{Binding local:comInitialiseWindows_CAN}"/>

我很确定我只是没有得到什么东西。或者我试图把事情复杂化,一个普通的按钮点击就足够了,因为它只是视图。

有什么建议吗?

在MVVM场景下,控件绑定到View而不是ViewModel

有两种可能:

通过ViewModel:你可以在ViewModel上公开一个属性:

class MainViewModel
{
    ICommand comInitialiseWindows  {get; set;}
}

在主窗口中:

MainViewModel vm = this.DataContext as MainViewModel;
vm.comInitialiseWindows  = new RelayCommand(() => comInitialiseWindows_DO(), comInitialiseWindows_CAN);
XAML:

<Button x:Name="ribbutLayoutWindows" Command="{Binding comInitialiseWindows}" />

注意:你不需要绑定IsEnabled属性。WPF将为您处理,并自动调用iccommand的canexecute方法。

通过DependencyProperty

在代码后面声明这个dependdecyproperty:

public ICommand comInitialiseWindows
{
    get { return (ICommand)GetValue(MyPropertyProperty); }
    set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty comInitialiseWindowsProperty = 
    DependencyProperty.Register("comInitialiseWindows", typeof(ICommand), typeof(MainWindow), new PropertyMetadata(null));

在代码后面赋值:

comInitialiseWindows = new RelayCommand(() => comInitialiseWindows_DO(), comInitialiseWindows_CAN);

之后,需要跳出XAML中的数据上下文。首先,给你的页面起一个名字:

<Window x:Class="Web_Media_Seeker_WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:local="clr-namespace:Web_Media_Seeker_WPF"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="myWindow"
        Title="MainWindow" Height="350" Width="525">

然后像这样声明你的绑定:

<Button x:Name="ribbutLayoutWindows" Command="{Binding comInitialiseWindows, ElementName=myWindow}" />