在MVVM中实现ICommand时,我遗漏了一些东西

时间:2013-04-16 17:19:48

标签: c# wpf mvvm icommand relaycommand

我对C#和WPF非常陌生,来自LAMP Web应用程序背景。我已经尝试过关于这个主题的几个教程,但是他们让我感到难过。

https://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/ http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

在第一个教程中,应用程序打开时带有一个简单的界面。一个TextBox和两个按钮。更新ProductId TextBox时,从0到1,“获取产品”按钮变为活动状态。单击“获取产品”按钮时,将显示DataTemplate的内容。我看不出这些事情究竟发生在哪里。是什么原因导致按钮变为活动状态?是什么原因导致表格出现?

希望你们和gals可以为我愚蠢=)

3 个答案:

答案 0 :(得分:4)

按钮会被激活或停用,因为它们已绑定到ICommandICommand包含CanExecute属性,用于确定按钮是否处于活动状态。

  

我无法看到这些事情实际发生在哪里。

该命令使用委托:

 _getProductCommand = new RelayCommand(
                param => GetProduct(),
                param => ProductId > 0
            );

CanExecute(委托返回true)时,第二个委托导致命令被激活(ProductId > 0变为真)。

单击该按钮时,命令的Execute方法将触发,然后执行操作。

对于首先启动的窗口,请查看标题为"启动样本&#34的部分; - app.xaml.cs中的代码,用于首先显示窗口。

答案 1 :(得分:1)

在该具体示例中,您可以看到:

<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ProductId}" />

TextBox使用data binding将其Text属性绑定到当前数据上下文(它是视图模型的一个实例)上的ProductId

TextBox中键入文本时,其值将自动更新在视图模型的ProductId属性中。

该命令检查ProductId的值是否大于0,以确定Button是否已启用。

您可以看到Button的命令设置为GetProductCommand

<Button ... Command="{Binding Path=GetProductCommand}" ... />

GetProductCommand使用表达式ProductId > 0作为其CanExecute谓词:

_getProductCommand = new RelayCommand(
              param => GetProduct(),
              param => ProductId > 0
);

WPF将执行此lambda表达式ProductId > 0,其结果将确定是否启用了Button。启用并单击该按钮后,将执行第一个lambda表达式 - GetProduct()

说完这一切之后,you really should be using an MVVM framework和这些框架还有其他机制来调用视图模型上的方法,这些方法已经超越了命令的一些限制。

答案 2 :(得分:1)

基本上MVVM或Model,View,ViewModel背后的理念是删除后面的代码并分离出应用程序的各个层,以便它们可以独立工作。 GUI或View和Viewmodel或代码隐藏之间的交互不会像你想象的那样发生。很多人对viewmodel实际上如何与gui或view进行交互感到困惑。我是一个带有代码隐藏文件的winforms开发者,您可以在后面的代码中轻松查看事件处理程序并按逻辑遵循代码。在您的MainWindow代码中,将XAML gui的数据上下文设置为视图模型。

public partial class MainWindow : Window
{
    #region Members
    SongViewModel _viewModel;
    int _count = 0;
    #endregion

    public MainWindow()
    {
        InitializeComponent();

        //  We have declared the view model instance declaratively in the xaml.
        //  Get the reference to it here, so we can use it in the button click event.
        _viewModel = (SongViewModel)base.DataContext;
    }

    private void ButtonUpdateArtist_Click(object sender, RoutedEventArgs e)
    {
        ++_count;
        _viewModel.ArtistName = string.Format("Elvis ({0})", _count);
    }
}    

然后{Binding Path = Property}将_viewModel的属性连接到XAML Elements。添加RaisePropertyChanged正在通知gui该属性的值已经改变。

public string ArtistName
    {
        get { return Song.ArtistName; }
        set
        {
            if (Song.ArtistName != value)
            {
                Song.ArtistName = value;
                RaisePropertyChanged("ArtistName");
            }
        }
    }

View模型的ArtistName属性在XAML中绑定到标签     

这是你在gui和代码之间或多或少的沟通。例如,在您的第一个示例中,当您将文本框从0更改为1时,然后更新ViewModel中的ProductID属性。您可以在ICommand GetProductCommand中看到有一个参数传递给relayCommand for ProductID&gt;现在,它的1 canexecute为true,因此命令现在可以执行,按钮变为可点击。单击它时GetProduct是发生的操作,然后该方法将使用值设置CurrentProduct属性。产品信息的Datatemplate绑定到xaml中的ProductModel,ProductModel绑定到CurrentProduct,因此现在在该datatemplate中,CurrentProduct的属性可以绑定到xaml元素,因此CurrentProduct.ProductName或绑定到

<TextBox Grid.Row="1" Grid.Column="1"  Text="{Binding ProductName}" />

起初令人困惑,但当你掌握它时,它将是完全合理的。