稳扎稳打Silverlight(52) - 4.0绑定之 ICommand 命令和 MVVM 模式
稳扎稳打Silverlight(52) - 4.0绑定之 ICommand 命令和 MVVM 模式
作者:webabcd
介绍
Silverlight 4.0 MVVM 模式:
- ICommand - 命令。可以将其绑定到 ButtonBase 或 Hyperlink 的 Command 属性上
- MVVM 模式 - Model-View-ViewModel
在线DEMO
http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html
示例
1、演示 ICommand 的应用
MyCommand.cs
代码
/*
* ICommand - 命令。可以将其绑定到 ButtonBase 或 Hyperlink 的 Command 属性上
* bool CanExecute(object parameter) - 当请命令是否可以执行
* event EventHandler CanExecuteChanged - 当请命令是否可以执行的状态发生改变时所触发的事件
* void Execute(object parameter) - 当前命令被执行时,所调用的方法
*/
using 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 Silverlight40.Binding.Command
{
public delegate void Execute(object parameter);
public delegate bool CanExecute(object parameter);
public class MyCommand : ICommand
{
private Execute _executeMethod;
private CanExecute _canExecuteMethod;
public MyCommand()
: this(null, null)
{
}
public MyCommand(Execute executeMethod)
: this(executeMethod, null)
{
}
public MyCommand(Execute executeMethod, CanExecute canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
public bool CanExecute(object parameter)
{
if (_canExecuteMethod == null)
return true;
else
return _canExecuteMethod(parameter);
}
public void Execute(object parameter)
{
if (_executeMethod != null)
_executeMethod(parameter);
}
public event EventHandler CanExecuteChanged;
protected virtual void OnCanExecuteChanged(EventArgs e)
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, e);
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged(EventArgs.Empty);
}
}
}
* ICommand - 命令。可以将其绑定到 ButtonBase 或 Hyperlink 的 Command 属性上
* bool CanExecute(object parameter) - 当请命令是否可以执行
* event EventHandler CanExecuteChanged - 当请命令是否可以执行的状态发生改变时所触发的事件
* void Execute(object parameter) - 当前命令被执行时,所调用的方法
*/
using 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 Silverlight40.Binding.Command
{
public delegate void Execute(object parameter);
public delegate bool CanExecute(object parameter);
public class MyCommand : ICommand
{
private Execute _executeMethod;
private CanExecute _canExecuteMethod;
public MyCommand()
: this(null, null)
{
}
public MyCommand(Execute executeMethod)
: this(executeMethod, null)
{
}
public MyCommand(Execute executeMethod, CanExecute canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
public bool CanExecute(object parameter)
{
if (_canExecuteMethod == null)
return true;
else
return _canExecuteMethod(parameter);
}
public void Execute(object parameter)
{
if (_executeMethod != null)
_executeMethod(parameter);
}
public event EventHandler CanExecuteChanged;
protected virtual void OnCanExecuteChanged(EventArgs e)
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, e);
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged(EventArgs.Empty);
}
}
}
MyViewModel.cs
代码
using 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 Silverlight40.Binding.Command
{
public class MyViewModel
{
// 声明一个 ICommand 类型,用于绑定到 ButtonBase 或 Hyperlink 的 Command 属性上
public ICommand Hello { get; set; }
public MyViewModel()
{
// 绑定了 Hello 的命令被执行时则会调用 ExecuteHello(object parameter) 方法
Hello = new MyCommand(ExecuteHello);
}
private void ExecuteHello(object parameter)
{
MessageBox.Show("Hello: " + parameter.ToString());
}
}
}
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 Silverlight40.Binding.Command
{
public class MyViewModel
{
// 声明一个 ICommand 类型,用于绑定到 ButtonBase 或 Hyperlink 的 Command 属性上
public ICommand Hello { get; set; }
public MyViewModel()
{
// 绑定了 Hello 的命令被执行时则会调用 ExecuteHello(object parameter) 方法
Hello = new MyCommand(ExecuteHello);
}
private void ExecuteHello(object parameter)
{
MessageBox.Show("Hello: " + parameter.ToString());
}
}
}
Demo.xaml
代码
<navigation:Page x:Class="Silverlight40.Binding.Command.Demo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:ViewModel="clr-namespace:Silverlight40.Binding.Command"
Title="Demo Page">
<Grid x:Name="LayoutRoot">
<Grid.DataContext>
<ViewModel:MyViewModel />
</Grid.DataContext>
<!--
Command - 指定需要关联的命令
CommandParameter - 传递给 Command 的参数
-->
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal" Height="20">
<TextBox Name="txtName" Text="webabcd" />
<Button Content="Hello" Command="{Binding Hello}" CommandParameter="{Binding ElementName=txtName, Path=Text }" />
</StackPanel>
</Grid>
</navigation:Page>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:ViewModel="clr-namespace:Silverlight40.Binding.Command"
Title="Demo Page">
<Grid x:Name="LayoutRoot">
<Grid.DataContext>
<ViewModel:MyViewModel />
</Grid.DataContext>
<!--
Command - 指定需要关联的命令
CommandParameter - 传递给 Command 的参数
-->
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal" Height="20">
<TextBox Name="txtName" Text="webabcd" />
<Button Content="Hello" Command="{Binding Hello}" CommandParameter="{Binding ElementName=txtName, Path=Text }" />
</StackPanel>
</Grid>
</navigation:Page>
2、MVVM 模式的 Demo
UpdateCommand.cs
代码
using 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 Silverlight40.Binding.MVVM
{
// 实现 ICommand 接口,在 MVVM 中它的作用是为 ButtonBase 或 Hyperlink 提供相应的行为逻辑
public class UpdateCommand : ICommand
{
private ProductViewModel _viewModel;
public UpdateCommand(ProductViewModel viewModel)
{
_viewModel = viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_viewModel.Update();
}
}
}
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 Silverlight40.Binding.MVVM
{
// 实现 ICommand 接口,在 MVVM 中它的作用是为 ButtonBase 或 Hyperlink 提供相应的行为逻辑
public class UpdateCommand : ICommand
{
private ProductViewModel _viewModel;
public UpdateCommand(ProductViewModel viewModel)
{
_viewModel = viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_viewModel.Update();
}
}
}
ProductViewModel.cs
代码
using 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;
using System.ComponentModel;
namespace Silverlight40.Binding.MVVM
{
// MVVM 之 ViewModel - 为了数据的绑定需要实现 INotifyPropertyChanged 接口;为了命令的绑定需要有相对应的 ICommand 类型的属性
public class ProductViewModel : INotifyPropertyChanged
{
public ProductViewModel()
: this (13, "wii")
{
}
public ProductViewModel(int productId, string name)
{
_productId = productId;
_name = name;
}
private int _productId;
public int ProductId
{
get { return _productId; }
set
{
_productId = value;
RaisePropertyChangedEvent("ProductId");
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChangedEvent("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public void Update()
{
MessageBox.Show(string.Format("将 ID 为 {0} 的名称更新为:{1}", _productId, _name));
}
public ICommand UpdateCommand
{
get
{
return new UpdateCommand(this);
}
}
}
}
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;
using System.ComponentModel;
namespace Silverlight40.Binding.MVVM
{
// MVVM 之 ViewModel - 为了数据的绑定需要实现 INotifyPropertyChanged 接口;为了命令的绑定需要有相对应的 ICommand 类型的属性
public class ProductViewModel : INotifyPropertyChanged
{
public ProductViewModel()
: this (13, "wii")
{
}
public ProductViewModel(int productId, string name)
{
_productId = productId;
_name = name;
}
private int _productId;
public int ProductId
{
get { return _productId; }
set
{
_productId = value;
RaisePropertyChangedEvent("ProductId");
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChangedEvent("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public void Update()
{
MessageBox.Show(string.Format("将 ID 为 {0} 的名称更新为:{1}", _productId, _name));
}
public ICommand UpdateCommand
{
get
{
return new UpdateCommand(this);
}
}
}
}
Demo.xaml
代码
<navigation:Page x:Class="Silverlight40.Binding.MVVM.Demo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:vm="clr-namespace:Silverlight40.Binding.MVVM"
Title="Demo Page">
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<!--数据源-->
<vm:ProductViewModel x:Key="productViewModel" />
</Grid.Resources>
<StackPanel HorizontalAlignment="Left" DataContext="{StaticResource productViewModel}">
<!--绑定属性-->
<TextBlock Text="{Binding ProductId}" />
<TextBox Text="{Binding Name, Mode=TwoWay}" />
<!--绑定命令-->
<Button Command="{Binding UpdateCommand}" Content="更新" />
</StackPanel>
</Grid>
</navigation:Page>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:vm="clr-namespace:Silverlight40.Binding.MVVM"
Title="Demo Page">
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<!--数据源-->
<vm:ProductViewModel x:Key="productViewModel" />
</Grid.Resources>
<StackPanel HorizontalAlignment="Left" DataContext="{StaticResource productViewModel}">
<!--绑定属性-->
<TextBlock Text="{Binding ProductId}" />
<TextBox Text="{Binding Name, Mode=TwoWay}" />
<!--绑定命令-->
<Button Command="{Binding UpdateCommand}" Content="更新" />
</StackPanel>
</Grid>
</navigation:Page>
OK
[源码下载]