Commands

In a Silverlight application, you can invoke some action in response to a user action (such as a button click) by creating an event handler in the code-behind class. However, in the MVVM pattern, the responsibility for implementing the action lies with the view model, and you should avoid placing code in the code-behind classes. Therefore, you should connect the control to a method in the view model using a binding.

The version of Silverlight on the Windows Phone 7 platform does not currently support binding to a command that implements the ICommand interface like you can do in Windows Presentation Foundation (WPF). Therefore, Tailspin uses a set of binding behaviors, including the ApplicationBarButtonNavigation, ApplicationBar ButtonCommand, and ButtonCommand behaviors, from the Prism Library to locate commands from the view.

For more information about the ICommand interface in WPF, see “Commanding Overview” on MSDN (http://msdn.microsoft.com/en-us/library/ms752308.aspx).

Inside the Implementation

The developers at Tailspin use bindings to associate actions in the UI with commands in the view model. In addition to Silverlight controls on the Windows Phone 7 platform not supporting binding to ICommand instances, you cannot use the InvokeCommandAction Expression Blend behavior with the ApplicationBarIconButton or Application BarMenuItems controls because they cannot have dependency properties. Tailspin uses a custom behavior to hook up commands to the view model.

The following code example from the SurveyListView page shows how the Synchronize button and the Settings button on the application bar are associated with commands.

XAML
<phoneNavigation:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible=”True”>
<shell:ApplicationBarIconButton Text=”Sync” IconUri=”…” />
<shell:ApplicationBarIconButton Text=”Settings”
IconUri=”…” />
<shell:ApplicationBarIconButton Text=”Filters” IconUri=”…”/>
</shell:ApplicationBar>
</phoneNavigation:PhoneApplicationPage.ApplicationBar>

<Custom:Interaction.Behaviors>
<prismInteractivity:ApplicationBarButtonCommand
ButtonText=”Sync”
CommandBinding=”{Binding StartSyncCommand}”/>
<prismInteractivity:ApplicationBarButtonCommand
ButtonText=”Settings”
CommandBinding=”{Binding AppSettingsCommand}” />
<prismInteractivity:ApplicationBarButtonCommand
ButtonText=”Filters”
CommandBinding=”{Binding FiltersCommand}” />

</Custom:Interaction.Behaviors>

The attributes attached to the ApplicationBarIconButton controls (Text and IconUri) only affect their appearance. The Application BarButtonCommand elements handle the connection to the commands; they identify the control to associate with the command through the ButtonText attribute and the command binding through the CommandBinding attribute.

The ApplicationBarButtonCommand class from the Prism Library implements the custom behavior and sets up the binding that links a button click in the UI to the StartSyncCommand, AppSettings Command, and FiltersCommand properties in the SurveyListView Model class.

The StartSyncCommand property uses an instance of the Delegate Command class that implements the ICommand interface. The following code example from the SurveyListViewModel class shows the definition of the StartSyncCommand property.

C#
public DelegateCommand StartSyncCommand { get; set; }

public SurveyListViewModel(…) : base(…)
{

this.StartSyncCommand = new DelegateCommand(
() => { this.StartSync(); },
() => !this.IsSynchronizing &&
!this.SettingAreNotConfigured);

}

 

Note: For more information about the DelegateCommand class from Prism, and to learn more about Prism, see the Prism CodePlex site (http://compositewpf.codeplex.com/).

The following code example from the SurveyListViewModel class shows the implementation of the StartSync method and Sync Completed method. These methods run the synchronization process asynchronously by invoking the StartSynchronization method; they also control the progress bar in the UI by setting the IsSynchronizing property. This method uses the ObserveOnDispatcher method from the Reactive Extensions (Rx) for .NET to run the synchronization
process.

C#
public void StartSync()
{
if (this.IsSynchronizing)
{
return;
}
this.IsSynchronizing = true;
this.synchronizationService
.StartSynchronization()
.ObserveOnDispatcher()
.Subscribe(
taskSummaries =>
{
this.SyncCompleted(taskSummaries);
this.IsSynchronizing = false;

});
}
private void SyncCompleted(
IEnumerable<TaskCompletedSummary> taskSummaries)
{

this.BuildPivotDimensions();
this.RaisePropertyChanged(string.Empty);
this.UpdateCommandsForSync();
}

The SyncCompleted method also updates the UI to show the new list of surveys following the synchronization process. The Update CommandsForSync method disables the Synchronize button in the UI while the synchronization is running.


Posted

in

by

Tags: