Pages

Showing posts with label Routed Commands. Show all posts
Showing posts with label Routed Commands. Show all posts

Monday, 2 February 2009

Passing an Enum as a CommandParameter

We wanted to pass an Enum as a CommandParameter and struggled to find the right syntax. The final result turned out to be straightforward.
xmlns:Util="clr-namespace:Sandstorm.Documents.FlexBlockBookings.Util


<RadioButton Name="rbPriceByActivity"
Content="By Activity"
Command="{Binding Path=BBChangePricingCommand}"
CommandParameter="{x:static Util:PricingOptions.ByActivity}"/>

Monday, 3 November 2008

DelegateCommand vs RoutedCommand vs EventHandler

I wanted to evaluate the difference between using the different types of Command mechanisms. The following code snippets aren't intended to be a working example, they simply highlight the code differences.


DelegateCommand
SimplePresenter.cs

public DelegateCommand<string> GetCustomerByDC { get; private set; }

GetCustomerByDC = new DelegateCommand(ExecuteGetCustomer, CanExecuteGetCustomer);

private void ExecuteGetCustomer(string parameter)
{
try
{
int customerId = int.Parse(parameter);
GetCustomer(customerId);
}
catch { }
}
}
private bool CanExecuteGetCustomer(string parameter)
{
try
{
int customerId = int.Parse(parameter);
return true;
}
catch
{
return false;
}
}

SimpleView.xaml.cs
ObjectDataProvider odpPresenter = (ObjectDataProvider)this.FindResource("MyPresenter");
Presenter = (SimplePresenter)odpPresenter.ObjectInstance;
Presenter.Model = newModel as SimpleModel;
Presenter.View = this;
private void txtCustomerId_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
Presenter.GetCustomerByDC.RaiseCanExecuteChanged();
}

SimpleView.xaml

xmlns:Presenters="clr-namespace:Sandstorm.Documents.Patterns.Presenters"
<ObjectDataProvider x:Key="MyPresenter" d:IsDataSource="True" ObjectType="{x:Type Presenters:SimplePresenter}"/>
<Button
x:Name="btnGetByDC"
Command="{Binding Source={StaticResource MyPresenter}, Path=GetCustomerByDC}"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By DelegateCommand</Button>
<TextBox
TextChanged="txtCustomerId_TextChanged"
/>

RoutedCommand

SimpleView.xaml.cs
private void GetCustomer_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
if (e.Parameter != null)
{
try
{
int customerId = int.Parse(e.Parameter as string);
Presenter.GetCustomer(customerId);
}
catch { }
}
}
private void GetCustomer_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
try
{
int customerId = int.Parse(e.Parameter as string);
e.CanExecute = true;
}
catch
{
e.CanExecute = false;
}
}

SimpleView.xaml
<UserControl.CommandBindings>
<CommandBinding
Command="local:LeisureCommands.GetCustomerCommand"
Executed="GetCustomer_Executed"
CanExecute="GetCustomer_CanExecute"
/>
</UserControl.CommandBindings>
<Button
x:Name="btnGetByRC"
Command="local:LeisureCommands.GetCustomerCommand"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By Routed Command</Button>

LeisureCommands.cs
public class LeisureCommands : RoutedUICommand
{
public readonly static RoutedUICommand GetCustomerCommand;
static LeisureCommands()
{
GetCustomerCommand = new RoutedUICommand("Get Customer...", "GetCustomerCommand", typeof(LeisureCommands));
GetCustomerCommand.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
}
}



Event
SimpleView.xaml.cs
private void btnGetByClick_Click(object sender, RoutedEventArgs e)
{
try
{
int customerId = int.Parse(txtCustomerId.Text);
Presenter.GetCustomer(customerId);
}
catch { }
}

SimpleView.xaml
<Button
x:Name="btnGetByClick"
Click="btnGetByClick_Click"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By Click Event</Button>


Lines of code
TypeRawOneOffPer CommandCan ExecuteTotal
DelegateCommand406341222
RoutedCommand457381226
Event15015n/a15


Conclusion
The RoutedCommand is a little more expensive in LOC terms than the DelegateCommand but the DelegateCommand does not support all the features of the RoutedCommand, in particular: Gestures.
If the "CanExecute" facility is not required the Event is by far the cheapest / easiest to implement.
I guess my conclusion was: "What are the DelegateCommands bringing to the party?"

Thursday, 30 October 2008

Routed Commands

Although we have opted to use the DelegateCommand<T> class in our project, this article gives a good overview of the Command pattern used in WPF.

The Command Pattern In Windows Presentation Foundation

DelegateCommand<T> class implements ICommand rather than subclassing RoutedCommand. The problem with this is that CanExecute is fired only once. RoutedCommands listen to a number of events and fire CanExecute quite frequently.
DelegateCommand<T> offers the RaiseCanExecuteChanged() method which can be fired manually when some "significant" event happens.
Alternatively a timer could be used to call RaiseCanExecuteChanged() at regular intervals. The following code sample uses a DispatcherTimer to raise the event on the UI thread.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_aTimer.Tick += new EventHandler(_aTimer_Tick);
_aTimer.Interval = new TimeSpan(0, 0, 1);
_aTimer.IsEnabled = false;
}

void _aTimer_Tick(object sender, EventArgs e)
{
_model.MyCommand.RaiseCanExecuteChanged();
}


These are the standard supplied commands:
ApplicationCommands—Close, Copy, Cut, Delete, Find, Help, New, Open, Paste, Print, PrintPreview, Properties, Redo, Replace, Save, SaveAs, SelectAll, Stop, Undo, and more

ComponentCommands—MoveDown, MoveLeft, MoveRight, MoveUp, ScrollByLine, ScrollPageDown, ScrollPageLeft, ScrollPageRight, ScrollPageUp, SelectToEnd, SelectToHome, SelectToPageDown, SelectToPageUp, and more

MediaCommands—ChannelDown, ChannelUp, DecreaseVolume, FastForward, IncreaseVolume, MuteVolume, NextTrack, Pause, Play, PreviousTrack, Record, Rewind, Select, Stop, and more

NavigationCommands—BrowseBack, BrowseForward, BrowseHome, BrowseStop, Favorites, FirstPage, GoToPage, LastPage, NextPage, PreviousPage, Refresh, Search, Zoom, and more

EditingCommands—AlignCenter, AlignJustify, AlignLeft, AlignRight, CorrectSpellingError, DecreaseFontSize, DecreaseIndentation, EnterLineBreak, EnterParagraphBreak, IgnoreSpellingError, IncreaseFontSize, IncreaseIndentation, MoveDownByLine, MoveDownByPage, MoveDownByParagraph, MoveLeftByCharacter, MoveLeftByWord, MoveRightByCharacter, MoveRightByWord, and more