AttachedBehavior pattern sample
The ClickBehavior is about the simplest I can think of. For illustration purposes I only included one command, but LeftClickCommand, DoubleClickCommand, MouseOverCommand etc. are all obvious extensions:
public static class ClickBehavior
{
public static DependencyProperty RightClickCommandProperty = DependencyProperty.RegisterAttached("RightClick",
typeof(ICommand),
typeof(ClickBehavior),
new FrameworkPropertyMetadata(null, new PropertyChangedCallback(ClickBehavior.RightClickChanged)));
public static void SetRightClick(DependencyObject target, ICommand value)
{
target.SetValue(ClickBehavior.RightClickCommandProperty, value);
}
public static ICommand GetRightClick(DependencyObject target) {
return (ICommand)target.GetValue(RightClickCommandProperty);
}
private static void RightClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
UIElement element = target as UIElement;
if (element != null)
{
// If we're putting in a new command and there wasn't one already
// hook the event
if ((e.NewValue != null) && (e.OldValue == null))
{
element.MouseRightButtonUp += element_MouseRightButtonUp;
}
// If we're clearing the command and it wasn't already null
// unhook the event
else if ((e.NewValue == null) && (e.OldValue != null))
{
element.MouseRightButtonUp -= element_MouseRightButtonUp;
}
}
}
static void element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
UIElement element = (UIElement)sender;
ICommand command = (ICommand)element.GetValue(ClickBehavior.RightClickCommandProperty);
command.Execute(null);
}
}
public class DelegateCommand : ICommand
{
public delegate void SimpleEventHandler();
private SimpleEventHandler handler;
private bool isEnabled = true;
public event EventHandler CanExecuteChanged;
public DelegateCommand(SimpleEventHandler handler)
{
this.handler = handler;
}
private void OnCanExecuteChanged()
{
if (this.CanExecuteChanged != null)
{
this.CanExecuteChanged(this, EventArgs.Empty);
}
}
bool ICommand.CanExecute(object arg)
{
return this.IsEnabled;
}
void ICommand.Execute(object arg)
{
this.handler();
}
public bool IsEnabled
{
get
{
return this.isEnabled;
}
set
{
this.isEnabled = value;
this.OnCanExecuteChanged();
}
}
}
public class ViewModel
{
public ICommand Foo
{
get
{
return new DelegateCommand(this.DoSomeAction);
}
}
private void DoSomeAction()
{
MessageBox.Show("Command Triggered");
}
}
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
<Window x:Class="WpfApplication1.Window1"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Content="Hello" local:ClickBehavior.RightClick="{Binding Foo}"/>
</Grid>
</Window>
Comments
Anonymous
May 16, 2008
Great simple, yet practical example. When I started building Caliburn, my first bits of functionality were very similar to this in implementation.Anonymous
May 16, 2008
PingBack from http://dogs-pets.info/dog-breeding/?p=959Anonymous
May 19, 2008
I like the pattern because you can build behavior independently of the inheritance hierarchy. I'm now trying to think of how to implement this elegantly as a replacement for data triggers on live bound data. I think it's just a matter of casting the data context of the control and wiring it up accordingly. But a better solution would probably be to use a class as the attached property and bind a property of that to the data itself - this way the behavior stays independent of the model. Any thoughts?Anonymous
May 27, 2009
One cool thing about DependencyProperties is the ability to have AttachedDependencyProperties (or Attached