MVVM模式的View與ViewModel的三大通訊方式:Binding Data(實現資料的傳遞)、Command(實現操作的調用)和Attached Behavior(實現控制項載入過程中的操作)。(1)Windows Phone 7 MVVM模式通訊方式之實現Binding Data。(2)Windows Phone 7 MVVM模式通訊方式之實現Command。(3)Windows Phone 7 MVVM模式通訊方式之實現Attached Behavior。下面通過一個執行個體實現MVVM模式的Command通訊(1)MainPage.xaml檔案的代碼,實現View層
<phone:PhoneApplicationPage x:Class="CommandDemo.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 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"> <!--設定整個頁面的上下文資料DataContext為RadiusViewModel--> <phone:PhoneApplicationPage.DataContext> <my:RadiusViewModel/> </phone:PhoneApplicationPage.DataContext> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <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}"/> </StackPanel> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Ellipse Fill="Red" 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:EventTrigger> </Custom:Interaction.Triggers> </Button> <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:EventTrigger> </Custom:Interaction.Triggers> </Button> <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:EventTrigger> </Custom:Interaction.Triggers> </Button> </Grid> </Grid></phone:PhoneApplicationPage>
(2)RadiusViewModel.cs檔案的代碼,實現ViewModel層
using System;using System.Windows.Input;using System.ComponentModel;using Microsoft.Expression.Interactivity.Core;namespace CommandDemo.ViewModel{ public class RadiusViewModel : INotifyPropertyChanged { private Double radius; public RadiusViewModel() { Radius = 0; 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 { get; private set; } public ICommand MedRadius { get; private set; } public ICommand MaxRadius { get; private set; } public Double Radius { get { return radius; } set { radius = value; 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;using System.Windows;using System.Windows.Input;using System.Windows.Interactivity;using System.Reflection;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) return; ICommand command = 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); break; } } if ((command != null) && command.CanExecute(CommandParameter)) { command.Execute(CommandParameter); } } private static bool IsCommandProperty(PropertyInfo property) { return typeof(ICommand).IsAssignableFrom(property.PropertyType); } public string CommandName { get { return (string)GetValue(CommandNameProperty); } set { SetValue(CommandNameProperty, value); } } public object CommandParameter { get { return GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } } }}