在这篇文章中,我将谈一下windows phone 7.1 Mango中的ICommand接口,怎么实现一个ICommand的实现类:DelegateCommand,以及怎么在MVVM Mango应用中使用。
当我们谈及Commands时,一般说来,Command有两个功能:
a:执行一个特殊的行为:command的主要功能。
b:确定某一UIElement的视觉状态(visual state):例如确定button是否可用。
DelegateCommand - ICommand可复用实现类
DelegateCommand:实现了ICommand,当需要使用command时,可用使用此类。(多在viewmodel中)
ICommand组成如下:
ICommand成员如下:
a:CanExecuteChanged事件和CanExecute方法被用来确定command所施加控件的视觉状态,它们是这样工作的:当某command施加于某控件时,控件会调用CanExecute方法,来确定初始的视觉状态,假设调用者是button,如果CanExecute方法返回false,button会被禁用。button同时也会订阅CanExecuteChanged事件。当触发CanExecuteChanged事件时,会再次调用CanExecute以确定是否需要修改视觉状态。
b:Execute方法比较直白:当需要执行某些行为操作时,控件会调用它。例如,当按下按钮时。
下面是DelegateCommand的代码清单:
DelegateCommandusing System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace WP7MangoDelegateCommandMVVM { public class DelegateCommand : ICommand { Func<object, bool> canExecute; Action<object> executeAction; public DelegateCommand(Action<object> executeAction) : this(executeAction, null) { } public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute) { if (executeAction == null) { throw new ArgumentNullException("executeAction"); } this.executeAction = executeAction; this.canExecute = canExecute; } public bool CanExecute(object parameter) { bool result = true; Func<object, bool> canExecuteHandler = this.canExecute; if (canExecuteHandler != null) { result = canExecuteHandler(parameter); } return result; } public event EventHandler CanExecuteChanged; public void RaiseCanExecuteChanged() { EventHandler handler = this.CanExecuteChanged; if (handler != null) { handler(this, new EventArgs()); } } public void Execute(object parameter) { this.executeAction(parameter); } } }
Windows Phone Mango MVVM 应用示例:
为了说明DelegateCommand的用法,我们使用MVVM模式,创建一windows phone 7.1 mango的应用程序,创建View、ViewModel和Model。
Model
此时,创建Person类,包含一个string类型的属性:
public class Person
{
public string Name
{
get;
set;
}
}
View Model
这是最重要的部分,使用了新创建的DelegateCommand类。我将创建PersonViewModel类,暴露ObservableCollection<Person>类型的DataSource属性和ICommand类型的LoadDataCommand属性。
public class PersonViewModel
{
private ObservableCollection<Person> personDataSource;
private ICommand loadDataCommand;
public PersonViewModel()
{
this.personDataSource = new ObservableCollection<Person>();
this.loadDataCommand = new DelegateCommand(this.LoadDataAction);
}
private void LoadDataAction(object p)
{
this.DataSource.Add(new Person() { Name = "John" });
this.DataSource.Add(new Person() { Name = "Kate" });
this.DataSource.Add(new Person() { Name = "Sam" });
}
public ICommand LoadDataCommand
{
get
{
return this.loadDataCommand;
}
}
public ObservableCollection<Person> DataSource
{
get
{
return this.personDataSource;
}
}
}
View
在这部分,我将添加一些UI元素,并通过ViewModel连接至数据,首先,需要为View设置DataContext,为简单起见,我仅是在View构造器中给DataContext设置为PersonViewModel的实例。
// Constructor
public MainPage()
{
InitializeComponent();
// simple way to bind the view to the view model
this.DataContext = new PersonViewModel();
}
接下来,绑定Command至button。
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Content="LoadData" Command="{Binding LoadDataCommand}" />
<ListBox ItemsSource="{Binding DataSource}"<div class="wlWriterEditableSmartContent" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:214b4eb9-c519-4afd-ad6d-bed19112debf" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><p> <a href="http://www.windowsphonegeek.com/upload/articles/WP7MangoDelegateCommand%20%282%29.zip" target="_blank">WPMangoDelegateCommandMVVM</a></p></div>>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
有关commands的更多信息,可参阅MSDN文档: