Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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