C# 在MVVM I';我错过了一些东西
一般来说,我对C#和WPF都很陌生,有着LAMP web应用程序的背景。我试着学习了一些关于这个主题的教程,但它们让我感到困惑 在第一个教程中,应用程序将打开一个简单的界面。一个文本框和两个按钮。更新ProductId文本框时,从0到1,“获取产品”按钮变为活动状态。当您单击“获取产品”按钮时,将显示DataTemplate的内容。我看不出这些事情到底发生在哪里。是什么导致按钮变为活动状态?是什么导致窗体出现的C# 在MVVM I';我错过了一些东西,c#,wpf,mvvm,icommand,relaycommand,C#,Wpf,Mvvm,Icommand,Relaycommand,一般来说,我对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}" />