2010-01-21 39 views
3

我希望能够将网格的双击路由到命令。我正在使用Rx来模拟双击,但我无法弄清楚将鼠标处理程序附加到哪个控件(DataGrid.RowLoading事件中的e.Row对象上的鼠标事件似乎不起作用)。将一行的双击绑定到Silverlight数据网格中的命令

任何人有任何想法?用于处理双击

的Rx代码如下:

Observable.FromEvent<MouseButtonEventArgs>(e.Row, "MouseLeftButtonDown").TimeInterval().Subscribe(evt => 
     { 
      if (evt.Interval.Milliseconds <= 300) 
      { 
       // Execute command on double click 
      } 
     }); 

回答

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(); 
    } 
} 
+0

嗨,任何机会分享你的整个命令样本? – Jordan 2011-03-02 14:10:51

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> 

没有运气。

相关问题