我希望能够将网格的双击路由到命令。我正在使用Rx模拟双击,但我无法弄清楚将鼠标处理程序附加到哪个控件(DataGrid.RowLoading事件中的e.Row对象上的鼠标事件似乎不起作用)。
有人有任何想法吗?
用于处理双击的Rx代码如下:
Observable.FromEvent<MouseButtonEventArgs>(e.Row, "MouseLeftButtonDown").TimeInterval().Subscribe(evt =>
{
if (evt.Interval.Milliseconds <= 300)
{
// Execute command on double click
}
});
答案 0 :(得分:4)
我将此代码从处理MouseLeftButtonDown更改为MouseLeftButtonUp,现在可以正常工作了。该行必须有其他处理按钮事件的内容。
Observable.FromEvent<MouseButtonEventArgs>(e.Row, "MouseLeftButtonUp").TimeInterval().Subscribe(evt =>
{
if (evt.Interval != TimeSpan.Zero && evt.Interval.TotalMilliseconds <= 300)
{
// Execute command on double click
}
});
完整的源代码包含在下面:
<强> CommandBehaviorBase.cs 强>
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
/// <summary>
/// Provides the base implementation of all Behaviors that can be attached to a <see cref="FrameworkElement"/> which trigger a command.
/// </summary>
/// <typeparam name="T">The type of control this behavior can be attached to, must derive from <see cref="FrameworkElement"/>.</typeparam>
public abstract class CommandBehaviorBase<T> : Behavior<T> where T : FrameworkElement
{
#region Constants and Fields
/// <summary>The DependencyProperty backing store for CommandParameter. This enables animation, styling, binding, etc...</summary>
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register(
"CommandParameter",
typeof(object),
typeof(CommandBehaviorBase<T>),
new PropertyMetadata(null, OnCommandParameterPropertyChanged));
/// <summary>The DependencyProperty backing store for Command. This enables animation, styling, binding, etc...</summary>
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
"Command", typeof(ICommand), typeof(CommandBehaviorBase<T>), new PropertyMetadata(null));
#endregion
/// <summary>
/// Gets or sets the command to execute
/// </summary>
public ICommand Command
{
get
{
return (ICommand)this.GetValue(CommandProperty);
}
set
{
this.SetValue(CommandProperty, value);
}
}
/// <summary>
/// Gets or sets the command parameter to execute with.
/// </summary>
public object CommandParameter
{
get
{
return this.GetValue(CommandParameterProperty);
}
set
{
this.SetValue(CommandParameterProperty, value);
}
}
/// <summary>
/// Gets or sets the command binding path (Hack for SL3).
/// </summary>
/// <remarks>This is a hack to overcome the fact that we cannot
/// bind to the Command dependency property due to a limitation in Silverlight 3.0
/// This shouldn't be necessary as in Silverlight 4.0 <see cref="DependencyObject"/> supports data binding hooray!</remarks>
public string CommandPath { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this mapping is currently enabled.
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// Implements the logic that disables the key mapping based on whether the command can be executed.
/// </summary>
/// <summary>
/// Updates the target object's IsEnabled property based on the commands ability to execute.
/// </summary>
public virtual void UpdateEnabledState()
{
if (this.Command == null && !string.IsNullOrEmpty(this.CommandPath))
{
this.Command = this.AssociatedObject.DataContext.GetPropertyPathValue<ICommand>(this.CommandPath, null);
}
if (this.AssociatedObject == null)
{
this.Command = null;
this.CommandParameter = null;
}
else if (this.Command != null)
{
this.IsEnabled = this.Command.CanExecute(this.CommandParameter);
}
}
/// <summary>
/// Executes the command, if it's set, providing the <see cref="CommandParameter"/>
/// </summary>
protected virtual void ExecuteCommand()
{
if (this.Command != null)
{
this.Command.Execute(this.CommandParameter);
}
}
/// <summary>
/// Attaches to the target <see cref="FrameworkElement"/> and sets up the command.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
this.UpdateEnabledState();
}
/// <summary>
/// Raised when the command parameter changes, re-evaluates whether the Command can execute
/// </summary>
/// <param name="sender">The KeyCommandBehavior that command parameter changed for.</param>
/// <param name="args">The parameter is not used.</param>
private static void OnCommandParameterPropertyChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((CommandBehaviorBase<T>)sender).UpdateEnabledState();
}
}
<强> DoubleClickCommandBehavior.cs 强>
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
/// <summary>
/// Provides behavior for any clickable control and will execute a command when the control is double clicked.
/// Does not disable the control if the command cannot be executed.
/// </summary>
public class DoubleClickCommandBehavior : CommandBehaviorBase<FrameworkElement>
{
#region Constants and Fields
/// <summary>
/// Stores the observable that subscribes to click events.
/// </summary>
private IDisposable observable;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the DoubleClickCommandBehavior class.
/// </summary>
public DoubleClickCommandBehavior()
{
// Default double-click interval is 220 milliseconds.
this.Interval = 220;
}
#endregion
/// <summary>
/// Gets or sets the double click interval in milliseconds.
/// </summary>
public int Interval
{
get;
set;
}
/// <summary>
/// Subscribes to the MouseLeftButtonUp of the data grid and times the intervals between the events,
/// if the time between clicks is less than the configured interval the command is executed.
/// </summary>
/// <remarks>Originally attached to MouseLeftButtonDown but the events were not firing.</remarks>
protected override void OnAttached()
{
base.OnAttached();
this.observable =
Observable.FromEvent<MouseButtonEventArgs>(this.AssociatedObject, "MouseLeftButtonUp").TimeInterval().
Subscribe(
evt =>
{
if (evt.Interval != TimeSpan.Zero && evt.Interval.TotalMilliseconds <= this.Interval)
{
this.UpdateEnabledState();
this.ExecuteCommand();
}
});
}
/// <summary>
/// Disposes of the observable
/// </summary>
protected override void OnDetaching()
{
if (this.observable != null)
{
this.observable.Dispose();
this.observable = null;
}
base.OnDetaching();
}
}
答案 1 :(得分:0)
我遇到了类似的问题(虽然没有使用Rx来处理双击,而是使用通用的DoubleClickTrigger)。我的具体问题与我不确定如何或在何处连接触发器这一事实有关。 我尝试过以下内容:
<data:DataGrid.Resources>
<ControlTemplate x:Key="rowTemplate" TargetType="data:DataGridRow">
<data:DataGridRow>
<fxui:Interaction.Triggers>
<fxui:DoubleClickTrigger>
<Interactivity:InvokeCommandAction Command="{Binding Source={StaticResource selectCommand}}" CommandParameter="{Binding}"/>
</fxui:DoubleClickTrigger>
</fxui:Interaction.Triggers>
</data:DataGridRow>
</ControlTemplate>
</data:DataGrid.Resources>
<data:DataGrid.RowStyle>
<Style TargetType="data:DataGridRow">
<Setter Property="Template" Value="{StaticResource rowTemplate}"/>
</Style>
</data:DataGrid.RowStyle>
没有运气。