I did this work with components (I love the component programming).
Trigger
I knew a trigger in Microsoft Blend named "ChangePropertyAction" (assembly "Microsoft.Expression.Interactions.dll") that is executed when an event is raised. But I had some difficulties in order to run it programmatically, so I inherited to this. I named it as "ManualChangePropertyAction" and it is quite simple, I just created the constructor with the required parameters, attached the object that will have the behavior and published a new method "Execute" to run the trigger.
using Microsoft.Expression.Interactivity.Core;
public class ManualChangePropertyAction : ChangePropertyAction
{
public ManualChangePropertyAction(UIElement associateObject, object targetObject, string propertyName, object value)
{
this.Attach(associateObject);
this.TargetObject = targetObject;
this.PropertyName = propertyName;
this.Value = value;
}
public void Execute()
{
this.Invoke(this.Value);
}
}
Behavior
Finally, I created the behavior pretty simple also. I have published four properties:
1.- TargetObject: The target object that will be affected by the behavior.
2.- PropertyName: The property that will change.
3.- Value: The new value for the specified property.
4.- MillisesondsForHoldClick: Number of milliseconds in order to consider the click action as a hold pressing action.
In the OnAttached and OnDetaching methods (from the Behavior<T> that inherit to), we just attach the event of "MouseLeftButtonDown" and "MouseLeftButtonUp". The first one initializes a datetime with the current time and the second one checks whether the elapsed time is greater than the MillisecondsForHoldClick property and, in this case, execute the above trigger:
/// <summary>
/// This behavior runs when the user has performed a hold click.
/// The specified property of the pointed target object will get changed with the value property.
/// </summary>
public class HoldClickBehavior : Behavior<UIElement>
{
/// <summary>
/// Target element property.
/// </summary>
public static readonly DependencyProperty TargetObjectProperty = DependencyProperty.Register("TargetObject",
typeof(object), typeof(HoldClickBehavior),
null);
/// <summary>
/// Property name property.
/// </summary>
public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register("PropertyName",
typeof(string), typeof(HoldClickBehavior),
null);
/// <summary>
/// Value of the property of the target element.
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",
typeof(object), typeof(HoldClickBehavior),
null);
/// <summary>
/// Value to specify the milliseconds in order to consider the click action as a hold action.
/// </summary>
public static readonly DependencyProperty MillisesondsForHoldClickProperty = DependencyProperty.Register("MillisesondsForHoldClick",
typeof(int), typeof(HoldClickBehavior),
new PropertyMetadata(1000));
/// <summary>
/// Property for the target object.
/// </summary>
public object TargetObject
{
get { return (object)GetValue(TargetObjectProperty); }
set { SetValue(TargetObjectProperty, value); }
}
/// <summary>
/// Property for the property name.
/// </summary>
public string PropertyName
{
get { return (string)GetValue(PropertyNameProperty); }
set { SetValue(PropertyNameProperty, value); }
}
/// <summary>
/// Property for the new value of the property.
/// </summary>
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
/// <summary>
/// Property to specify the milliseconds in order to consider the click action as a hold action.
/// </summary>
public int MillisesondsForHoldClick
{
get { return (int)GetValue(MillisesondsForHoldClickProperty); }
set { SetValue(MillisesondsForHoldClickProperty, value); }
}
/// <summary>
/// Field to know when the user has clicked.
/// </summary>
private DateTime clickDownDateTime;
/// <summary>
/// Attach the specified element where the behavior will start.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
// Register event handlers
this.AssociatedObject.MouseLeftButtonDown += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
this.AssociatedObject.MouseLeftButtonUp += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp);
}
/// <summary>
/// Dettach the specified element where the behavior will start.
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
// Deregister event handlers
this.AssociatedObject.MouseLeftButtonDown -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
this.AssociatedObject.MouseLeftButtonUp -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp);
}
/// <summary>
/// Perform the action if it is a hold action.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if ((DateTime.Now.Subtract(this.clickDownDateTime).TotalMilliseconds) > this.MillisesondsForHoldClick)
{
object element = this.TargetObject;
if (element != null)
{
ManualChangePropertyAction action = new ManualChangePropertyAction(this.AssociatedObject, element, this.PropertyName, this.Value);
action.Run();
}
e.Handled = true;
}
}
/// <summary>
/// Initializes the time when the user has clicked.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.clickDownDateTime = DateTime.Now;
}
}
And this is all. The usage is like the following example:
<Grid Cursor="Hand"
Width="75"
Margin="0">
<i:Interaction.Behaviors>
<behaviors:HoldClickBehavior TargetObject="{Binding ElementName=container}"
PropertyName="Visibility"
Value="Visible"/>
</i:Interaction.Behaviors>
<Grid x:Name="container" Visibility="Collapsed">
</Grid>
</Grid>Width="75"
Margin="0">
<i:Interaction.Behaviors>
<behaviors:HoldClickBehavior TargetObject="{Binding ElementName=container}"
PropertyName="Visibility"
Value="Visible"/>
</i:Interaction.Behaviors>
<Grid x:Name="container" Visibility="Collapsed">
</Grid>
I hope you like this post.
Enjoy!
No hay comentarios:
Publicar un comentario