// --------------------------------------------------------------------------------------------------------------------
// <copyright file="EventToCommand.cs" company="Catel development team">
// Copyright (c) 2008 - 2011 Catel development team. All rights reserved.
// </copyright>
// <summary>
// Class to binding any event to a command.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace Catel.MVVM.Commands
{
/// <summary>
///
/// </summary>
/// <remarks>
/// This class is based on the implementation of the <c>EventToCommand</c> class that can be found
/// in the MVVM Light Toolkit (see http://mvvmlight.codeplex.com/).
/// </remarks>
public class EventToCommand : TriggerAction<FrameworkElement>
{
#region Variables
#endregion
#region Constructor & destructor
#endregion
#region Properties
/// <summary>
/// Gets or sets a value indicating whether the <see cref="EventArgs"/> passed to the event handler
/// should be passed to the command as well.
/// </summary>
/// <value>
/// <c>true</c> if the <see cref="EventArgs"/> passed to the event handler should be passed to the command; otherwise, <c>false</c>.
/// </value>
public bool PassEventArgsToCommand { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the associated object should be disabled when the command
/// cannot be executed.
/// </summary>
/// <remarks>
/// Wrapper for the DisableAssociatedObjectOnCannotExecute dependency property.
/// </remarks>
public bool DisableAssociatedObjectOnCannotExecute
{
get { return (bool)GetValue(DisableAssociatedObjectOnCannotExecuteProperty); }
set { SetValue(DisableAssociatedObjectOnCannotExecuteProperty, value); }
}
/// <summary>
/// DependencyProperty definition as the backing store for DisableAssociatedObjectOnCannotExecute.
/// </summary>
public static readonly DependencyProperty DisableAssociatedObjectOnCannotExecuteProperty =
DependencyProperty.Register("DisableAssociatedObjectOnCannotExecute", typeof(bool), typeof(EventToCommand), new PropertyMetadata(true,
(sender, e) => ((EventToCommand)sender).UpdateElementState()));
/// <summary>
/// Gets or sets the associated Command.
/// </summary>
/// <remarks>
/// Wrapper for the Command dependency property.
/// </remarks>
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
/// <summary>
/// DependencyProperty definition as the backing store for Command.
/// </summary>
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(EventToCommand), new PropertyMetadata(null,
(sender, e) => ((EventToCommand)sender).OnCommandChanged(sender, e)));
/// <summary>
/// Gets or sets the command parameter.
/// </summary>
/// <remarks>
/// Wrapper for the CommandParameter dependency property.
/// </remarks>
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
/// <summary>
/// DependencyProperty definition as the backing store for CommandParameter.
/// </summary>
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(EventToCommand), new PropertyMetadata(null,
(sender, e) => ((EventToCommand)sender).UpdateElementState()));
#endregion
#region Methods
/// <summary>
/// Called when the <see cref="Command"/> property has changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private void OnCommandChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue is ICommand)
{
((ICommand)e.OldValue).CanExecuteChanged -= OnCommandCanExecuteChanged;
}
if (e.NewValue is ICommand)
{
((ICommand)e.NewValue).CanExecuteChanged += OnCommandCanExecuteChanged;
}
UpdateElementState();
}
/// <summary>
/// Called when the <c>CanExecute</c> state of a command has changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnCommandCanExecuteChanged(object sender, EventArgs e)
{
UpdateElementState();
}
/// <summary>
/// Invokes the action without any parameter.
/// </summary>
public void Invoke()
{
Invoke(null);
}
/// <summary>
/// Invokes the action.
/// </summary>
/// <param name="parameter">The parameter to the action. If the Action does not require a parameter, the parameter may be set to a null reference.</param>
protected override void Invoke(object parameter)
{
if (IsAssociatedObjectDisabled() || (Command == null))
{
return;
}
object commandParameter = CommandParameter;
if ((commandParameter == null) && PassEventArgsToCommand)
{
commandParameter = parameter;
}
if (Command.CanExecute(commandParameter))
{
Command.Execute(commandParameter);
}
}
/// <summary>
/// Checks whether the associated object is disabled or not.
/// </summary>
/// <returns><c>true</c> if the associated object is disabled; otherwise <c>false</c>.</returns>
private bool IsAssociatedObjectDisabled()
{
#if SILVERLIGHT
return false;
#else
return ((AssociatedObject != null) && !AssociatedObject.IsEnabled);
#endif
}
/// <summary>
/// Updates the state of the associated element.
/// </summary>
private void UpdateElementState()
{
if ((AssociatedObject == null) || (Command == null))
{
return;
}
#if !SILVERLIGHT
AssociatedObject.IsEnabled = DisableAssociatedObjectOnCannotExecute ? Command.CanExecute(CommandParameter) : true;
// TODO: Check if we can actually set it to true, or maybe we shouldn't do anything at all
#endif
}
/// <summary>
/// Called when this trigger is attached to a <see cref="FrameworkElement"/>.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
UpdateElementState();
}
#endregion
}
}