MVVM模式的View与ViewModel的三大通讯方式:Binding Data(实现数据的传递)、Command(实现操作的调用)和Attached Behavior(实现控件加载过程中的操作)。
下面通过一个实例实现MVVM模式的Command通讯
(1)MainPage.xaml文件的代码,实现View层
< phone:PhoneApplicationPage |
x:Class = "CommandDemo.MainPage" |
xmlns:phone = "clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" |
xmlns:shell = "clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" |
xmlns:my = "clr-namespace:CommandDemo.ViewModel" |
xmlns:my_Interactivity = "clr-namespace:CommandDemo.Command" |
xmlns:Custom = "clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:ic = "clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" |
mc:Ignorable = "d" d:DesignWidth = "480" d:DesignHeight = "768" |
FontFamily = "{StaticResource PhoneFontFamilyNormal}" |
FontSize = "{StaticResource PhoneFontSizeNormal}" |
Foreground = "{StaticResource PhoneForegroundBrush}" |
SupportedOrientations = "Portrait" Orientation = "Portrait" |
shell:SystemTray.IsVisible = "True" > |
< phone:PhoneApplicationPage.DataContext > |
</ phone:PhoneApplicationPage.DataContext > |
< Grid x:Name = "LayoutRoot" Background = "Transparent" > |
< RowDefinition Height = "Auto" /> |
< RowDefinition Height = "*" /> |
< StackPanel x:Name = "TitlePanel" Grid.Row = "0" Margin = "12,17,0,28" > |
< TextBlock x:Name = "ApplicationTitle" Text = "MY APPLICATION" Style = "{StaticResource PhoneTextNormalStyle}" /> |
< TextBlock x:Name = "PageTitle" Text = "Command" Margin = "9,-7,0,0" Style = "{StaticResource PhoneTextTitle1Style}" /> |
< Grid x:Name = "ContentPanel" Grid.Row = "1" Margin = "12,0,12,0" > |
Height = "{Binding Radius}" Width = "{Binding Radius}" |
HorizontalAlignment = "Left" Margin = "119,84,0,0" Name = "ellipse1" Stroke = "Black" StrokeThickness = "1" VerticalAlignment = "Top" /> |
< Button Content = "小" Height = "72" HorizontalAlignment = "Left" Margin = "0,385,0,0" Name = "button1" VerticalAlignment = "Top" Width = "160" > |
< Custom:Interaction.Triggers > |
< Custom:EventTrigger EventName = "Click" > |
< my_Interactivity:ExecuteCommandAction CommandName = "MinRadius" /> |
</ Custom:Interaction.Triggers > |
< Button Content = "中" Height = "72" HorizontalAlignment = "Left" Margin = "149,384,0,0" Name = "button2" VerticalAlignment = "Top" Width = "160" > |
< Custom:Interaction.Triggers > |
< Custom:EventTrigger EventName = "Click" > |
< my_Interactivity:ExecuteCommandAction CommandName = "MedRadius" /> |
</ Custom:Interaction.Triggers > |
< Button Content = "大" Height = "72" HorizontalAlignment = "Left" Margin = "299,382,0,0" Name = "button3" VerticalAlignment = "Top" Width = "160" > |
< Custom:Interaction.Triggers > |
< Custom:EventTrigger EventName = "Click" > |
< my_Interactivity:ExecuteCommandAction CommandName = "MaxRadius" /> |
</ Custom:Interaction.Triggers > |
</ phone:PhoneApplicationPage > |
(2)RadiusViewModel.cs文件的代码,实现ViewModel层
using System.Windows.Input; |
using System.ComponentModel; |
using Microsoft.Expression.Interactivity.Core; |
namespace CommandDemo.ViewModel |
public class RadiusViewModel : INotifyPropertyChanged |
MinRadius = new ActionCommand(p => Radius = 100); |
MedRadius = new ActionCommand(p => Radius = 200); |
MaxRadius = new ActionCommand(p => Radius = 300); |
public event PropertyChangedEventHandler PropertyChanged; |
public ICommand MinRadius |
public ICommand MedRadius |
public ICommand MaxRadius |
OnPropertyChanged( "Radius" ); |
protected virtual void OnPropertyChanged( string propertyName) |
var propertyChanged = PropertyChanged; |
if (propertyChanged != null ) |
propertyChanged( this , new PropertyChangedEventArgs(propertyName)); |
(3)ExecuteCommandAction.cs类,实现Command操作
using System.Windows.Input; |
using System.Windows.Interactivity; |
namespace CommandDemo.Command |
public class ExecuteCommandAction : TriggerAction<FrameworkElement> |
public static readonly DependencyProperty CommandNameProperty = |
DependencyProperty.Register( "CommandName" , typeof ( string ), typeof (ExecuteCommandAction), null ); |
public static readonly DependencyProperty CommandParameterProperty = |
DependencyProperty.Register( "CommandParameter" , typeof ( object ), typeof (ExecuteCommandAction), null ); |
protected override void Invoke( object parameter) |
if (AssociatedObject == null ) |
var dataContext = AssociatedObject.DataContext; |
foreach (var info in dataContext.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) |
if (IsCommandProperty(info) && String.Equals(info.Name, CommandName, StringComparison.Ordinal)) |
command = (ICommand)info.GetValue(dataContext, null ); |
if ((command != null ) && command.CanExecute(CommandParameter)) |
command.Execute(CommandParameter); |
private static bool IsCommandProperty(PropertyInfo property) |
return typeof (ICommand).IsAssignableFrom(property.PropertyType); |
public string CommandName |
return ( string )GetValue(CommandNameProperty); |
SetValue(CommandNameProperty, value); |
public object CommandParameter |
return GetValue(CommandParameterProperty); |
SetValue(CommandParameterProperty, value); |