C# 在MVVM I';我错过了一些东西

C# 在MVVM I';我错过了一些东西,c#,wpf,mvvm,icommand,relaycommand,C#,Wpf,Mvvm,Icommand,Relaycommand,一般来说,我对C#和WPF都很陌生,有着LAMP web应用程序的背景。我试着学习了一些关于这个主题的教程,但它们让我感到困惑 在第一个教程中,应用程序将打开一个简单的界面。一个文本框和两个按钮。更新ProductId文本框时,从0到1,“获取产品”按钮变为活动状态。当您单击“获取产品”按钮时,将显示DataTemplate的内容。我看不出这些事情到底发生在哪里。是什么导致按钮变为活动状态?是什么导致窗体出现的 希望你们这些家伙和女孩能帮我把它哑下来=)这些按钮会被激活或停用,因为它们被绑定

一般来说,我对C#和WPF都很陌生,有着LAMP web应用程序的背景。我试着学习了一些关于这个主题的教程,但它们让我感到困惑

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


希望你们这些家伙和女孩能帮我把它哑下来=)

这些按钮会被激活或停用,因为它们被绑定到一个
ICommand
ICommand
包含一个属性,用于确定按钮是否处于活动状态

我看不出这些事情到底发生在哪里

该命令使用委托:

 _getProductCommand = new RelayCommand(
                param => GetProduct(),
                param => ProductId > 0
            );
ProductId>0
时,第二个委托导致命令被激活(
CanExecute
变为true)(委托返回true)

单击该按钮时,命令的
Execute
方法将激发并执行操作


至于首先启动的窗口,请查看标题为“启动示例”的部分-
app.xaml.cs
中有代码,用于首先显示窗口。

在该特定示例中,您可以看到:

<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ProductId}" />
GetProductCommand
使用表达式
ProductId>0
作为其
CanExecute
谓词:

_getProductCommand = new RelayCommand(
              param => GetProduct(),
              param => ProductId > 0
);
WPF将执行此lambda表达式
ProductId>0
,其结果将确定
按钮是否已启用。启用并单击按钮后,将执行第一个lambda表达式-
GetProduct()


综上所述,这些框架还有其他机制来调用视图模型上的方法,这些机制克服了命令的一些限制。

基本上,MVVM或model、view、ViewModel背后的思想是删除这些代码,并分离出应用程序的各个层,以便它们可以独立工作。GUI或视图与Viewmodel或codebehind之间的交互不会像您可能认为的那样发生。很多人对viewmodel实际上如何与gui或视图交互感到困惑。我是一名winforms开发人员,拥有代码隐藏文件,在该文件中,您可以很容易地看到代码隐藏中的事件处理程序,并在逻辑上遵循代码。在主窗口代码中,将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元素。添加RaisePropertyChanged会通知gui该属性的值已更改

public string ArtistName
    {
        get { return Song.ArtistName; }
        set
        {
            if (Song.ArtistName != value)
            {
                Song.ArtistName = value;
                RaisePropertyChanged("ArtistName");
            }
        }
    }
视图模型的ArtistName属性绑定到标签,就像在XAML中一样

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

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


一开始它让人困惑,但当你掌握了窍门后,它就完全有意义了。

它有点长(我知道我有偏见),但如果你还不熟悉WPF,我认为我关于MVVM的系列更容易理解。我有一篇完整的文章,它以一种比你正在阅读的文章更基本的方式贯穿其中。再次感谢里德,我一定会看的!我盯着代码看了一会儿,慢慢地,非常缓慢地,我开始摸索到底发生了什么。我还有一个问题。如果我想双击我的按钮呢?或者这是一个框架能够比我所包含的教程示例更容易解决的问题吗?Caliburn.Micro()之类的东西提供了“Actions”,例如,它可以让您非常轻松地从按钮的MouseDoubleClick事件中调用视图模型上的方法。非常感谢。花了一点时间,但终于能够理解发生了什么。我原本期望某个方法实际打开按钮,而不是它的活动状态是谓词(第二个lambda参数,对于像我一样困惑的人)为真的结果。@lose\u grimm谓词是一个方法-每当
CanExecuteChanged
触发时,它都会运行,或者当WPF决定检查它时。我的陈述不准确吗?@lose_the_grimm不-它是准确的-你提到你“期望某个方法实际打开按钮”-谓词是这样做的方法,但它是间接的。也许这表明我还没有完全理解它。在本例中,是什么决定了绑定到按钮的命令是由单击触发的,而不是双击触发的。甚至是悬停,还是聚焦?
<TextBox Grid.Row="1" Grid.Column="1"  Text="{Binding ProductName}" />