Prism Commanding allows designers/develops to specify, in XAML, events that fire back into the View Model/Presenter. Imagine this: the user hovers a mouse over a Silverlight control. Commanding allows that action to be bound to a method (more specifically, a delegate) in the ViewModel. The View Model then handles that action. This Commanding support overcomes a deficiency (lack of ICommand implementation) in Silverlight that makes proper MVVM implementation difficult. If you're using MVVM, Commanding is a must. That can take the form of a home-grown solution, Prism or any of a number of other libraries: Caliburn, Silverlight.FX, etc. In Prism Commanding, the Commands are implemented as attached properties. This video shows how to use the existing command (button click), handle command parameters, use the CanExecute functionality, and create new commands.
public class ModuleAViewModel : INotifyPropertyChanged
{
Brush normal = new SolidColorBrush(Colors.White);
Brush blue = new SolidColorBrush(Colors.Blue);
public ModuleAViewModel()
{
Companies = new ObservableCollection<Company>();
HighlightItems = normal;
}
//Services
public ICompanyService CompanyService { get; set; }
//General Properties
public ObservableCollection<Company> Companies { get; set; }
public Brush HighlightItems { get; set; }
//Commands
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
//Commands
public DelegateCommand<object> GetCompanyData { get; set; }
public ModuleAViewModel()
{
Companies = new ObservableCollection<Company>();
GetCompanyData = new DelegateCommand<object>(o =>
{
if (CompanyService != null)
{
Companies.Clear();
foreach (Company c in CompanyService.getCompanies())
Companies.Add(c);
}
});
HighlightItems = normal;
}
xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
<Button Content="SimpleButton"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
cal:Click.Command="{Binding GetCompanyData}"
/>
GetCompanyData = new DelegateCommand<object>(o =>
{
if (CompanyService != null)
{
Companies.Clear();
foreach (Company c in CompanyService.getCompanies())
Companies.Add(c);
}
}, o =>
{
return true;
});
<Button Content="SimpleButton"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
cal:Click.Command="{Binding GetCompanyData}"
cal:Click.CommandParameter="SimpleButton"
/>
public class MouseOverBehavior : CommandBehaviorBase<Control>
{
public MouseOverBehavior(Control element)
: base(element)
{
element.MouseEnter += new MouseEventHandler(element_MouseEnter);
}
void element_MouseEnter(object sender, MouseEventArgs e)
{
base.ExecuteCommand();
}
}
public class CommandBehaviorBase<T> where T : System.Windows.Controls.Control
{
public CommandBehaviorBase(T targetObject);
public ICommand Command { get; set; }
public object CommandParameter { get; set; }
protected T TargetObject { get; }
protected virtual void ExecuteCommand();
protected virtual void UpdateEnabledState();
}
public static class MouseOver
{
public static ICommand GetCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(CommandProperty, value);
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(MouseOver), new PropertyMetadata(OnSetCommandCallback));
private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
Control element = dependencyObject as Control;
if (element != null)
{
MouseOverBehavior behavior = GetOrCreateBehavior(element);
behavior.Command = e.NewValue as ICommand;
}
}
private static MouseOverBehavior GetOrCreateBehavior(Control element)
{
MouseOverBehavior behavior = element.GetValue(MouseOverCommandBehaviorProperty) as MouseOverBehavior;
if (behavior == null)
{
behavior = new MouseOverBehavior(element);
element.SetValue(MouseOverCommandBehaviorProperty, behavior);
}
return behavior;
}
public static MouseOverBehavior GetMouseOverCommandBehavior(DependencyObject obj)
{
return (MouseOverBehavior)obj.GetValue(MouseOverCommandBehaviorProperty);
}
public static void SetMouseOverCommandBehavior(DependencyObject obj, MouseOverBehavior value)
{
obj.SetValue(MouseOverCommandBehaviorProperty, value);
}
// Using a DependencyProperty as the backing store for MouseOverCommandBehavior. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MouseOverCommandBehaviorProperty =
DependencyProperty.RegisterAttached("MouseOverCommandBehavior",
typeof(MouseOverBehavior), typeof(MouseOver), null);
}
public class ModuleAViewModel : INotifyPropertyChanged
{
Brush normal = new SolidColorBrush(Colors.White);
Brush blue = new SolidColorBrush(Colors.Blue);
public ModuleAViewModel()
{
Companies = new ObservableCollection<Company>();
GetCompanyData = new DelegateCommand<object>(o =>
{
if (CompanyService != null)
{
Companies.Clear();
foreach (Company c in CompanyService.getCompanies())
Companies.Add(c);
}
}, o =>
{
return true;
});
MousedOver = new DelegateCommand<object>(itemMousedOver);
HighlightItems = normal;
}
//Services
public ICompanyService CompanyService { get; set; }
//General Properties
public ObservableCollection<Company> Companies { get; set; }
public Brush HighlightItems { get; set; }
//Commands
public DelegateCommand<object> GetCompanyData { get; set; }
public DelegateCommand<object> MousedOver { get; set; }
public void itemMousedOver(object o)
{
HighlightItems = blue;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("HighlightItems"));
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
xmlns:commands="clr-namespace:Infrastructure.Commands;assembly=Infrastructure"
<ListBox Width="250"
Height="200"
ItemsSource="{Binding Companies, Mode=TwoWay}"
Background="{Binding HighlightItems, Mode=OneWay}"
commands:MouseOver.Command="{Binding MousedOver}"
>
<Button Content="SimpleButton"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
cal:Click.Command="{Binding GetCompanyData}"
cal:Click.CommandParameter="SimpleButton"
commands:MouseOver.Command="{Binding MousedOver}"
/>
If you're unfamiliar with the MVVM pattern, this video shows you how to do it in Silverlight. The benefit of this pattern is that it allows us to have more maintainable and testable applications.
This video shows you how to get started with Prism in Silverlight. There's a lot in Prism, and this video shows you how to get a Prism project up and running.
This is an interview with the Patterns and Practices team at Microsoft and Shawn Wildermuth. They explain when to use Prism and when not to.