Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
OnPropertyChangedCommandBehavior.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Linq;
5 using System.Windows.Interactivity;
6 
7 using SiliconStudio.Presentation.Core;
8 using SiliconStudio.Presentation.Extensions;
9 using System.Windows;
10 using System.Windows.Input;
11 using System.Windows.Data;
12 
13 namespace SiliconStudio.Presentation.Behaviors
14 {
15  /// <summary>
16  /// A <see cref="Behavior"/> that allow to execute a command when the value of a dependency property of its associated
17  /// object changes, or when the source of the dependency property binding is updated.
18  /// </summary>
19  public class OnPropertyChangedCommandBehavior : Behavior<FrameworkElement>
20  {
21  private string propertyName;
22  private readonly DependencyPropertyWatcher propertyWatcher = new DependencyPropertyWatcher();
23  private DependencyProperty dependencyProperty;
24 
25  /// <summary>
26  /// Identifies the <see cref="Command"/> dependency property.
27  /// </summary>
28  public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(OnPropertyChangedCommandBehavior));
29 
30  /// <summary>
31  /// Identifies the <see cref="CommandParameter"/> dependency property.
32  /// </summary>
33  public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(OnPropertyChangedCommandBehavior));
34 
35  /// <summary>
36  /// Identifies the <see cref="ExecuteOnlyOnSourceUpdate"/> dependency property.
37  /// </summary>
38  public static readonly DependencyProperty ExecuteOnlyOnSourceUpdateProperty = DependencyProperty.Register("ExecuteOnlyOnSourceUpdate", typeof(bool), typeof(OnPropertyChangedCommandBehavior));
39 
40  /// <summary>
41  /// Gets or sets the name of the dependency property that will trigger the associated command.
42  /// </summary>
43  /// <remarks>Changing this property after the behavior has been attached will have no effect.</remarks>
44  public string PropertyName { get { return propertyName; } set { if (AssociatedObject == null) propertyName = value; } }
45 
46  /// <summary>
47  /// Gets or sets the command to execute when the property is modified.
48  /// </summary>
49  public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } }
50 
51  /// <summary>
52  /// Gets or sets the parameter of the command to execute when the property is modified.
53  /// </summary>
54  public object CommandParameter { get { return GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } }
55 
56  /// <summary>
57  /// Gets or set whether the command should be executed only when the source of the binding associated to the dependency property is updated.
58  /// </summary>
59  /// <remarks>If set to <c>true</c>, this property requires that a binding exists on the dependency property and that it has <see cref="Binding.NotifyOnSourceUpdated"/> set to <c>true</c>.</remarks>
60  public bool ExecuteOnlyOnSourceUpdate { get { return (bool)GetValue(ExecuteOnlyOnSourceUpdateProperty); } set { SetValue(ExecuteOnlyOnSourceUpdateProperty, value); } }
61 
62  protected override void OnAttached()
63  {
64  if (PropertyName == null)
65  throw new ArgumentException(string.Format("The PropertyName property must be set on behavior '{0}'.", GetType().FullName));
66 
67  dependencyProperty = AssociatedObject.GetDependencyProperties(true).FirstOrDefault(dp => dp.Name == PropertyName);
68  if (dependencyProperty == null)
69  throw new ArgumentException(string.Format("Unable to find property '{0}' on object of type '{1}'.", PropertyName, AssociatedObject.GetType().FullName));
70 
71  propertyWatcher.Attach(AssociatedObject);
72  // TODO: Register/Unregister handlers when the PropertyName changes
73  propertyWatcher.RegisterValueChangedHandler(dependencyProperty, OnPropertyChanged);
74  Binding.AddSourceUpdatedHandler(AssociatedObject, OnSourceUpdated);
75  }
76 
77  protected override void OnDetaching()
78  {
79  propertyWatcher.Detach();
80  base.OnDetaching();
81  }
82 
83  private void OnSourceUpdated(object sender, DataTransferEventArgs e)
84  {
85  if (ExecuteOnlyOnSourceUpdate && e.Property == dependencyProperty)
86  {
87  ExecuteCommand();
88  }
89  }
90 
91  private void OnPropertyChanged(object sender, EventArgs e)
92  {
93  if (!ExecuteOnlyOnSourceUpdate)
94  {
95  ExecuteCommand();
96  }
97  }
98 
99  private void ExecuteCommand()
100  {
101  if (Command == null || !Command.CanExecute(CommandParameter))
102  return;
103 
104  Command.Execute(CommandParameter);
105  }
106  }
107 }
A Behavior that allow to execute a command when the value of a dependency property of its associated ...