【问题标题】:Binding double click of a row to a command in a Silverlight Data Grid将双击行绑定到 Silverlight 数据网格中的命令
【发布时间】:2011-01-07 13:55:52
【问题描述】:

我希望能够将网格的双击路由到命令。我正在使用 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
            }
        });

【问题讨论】:

    标签: silverlight datagrid


    【解决方案1】:

    我将此代码从处理 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();
        }
    }
    

    【讨论】:

      【解决方案2】:

      我遇到了类似的问题(尽管没有使用 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>
      

      没有运气。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-29
        • 2010-10-09
        • 1970-01-01
        • 2012-06-13
        • 2012-01-29
        • 2011-11-29
        • 1970-01-01
        • 2011-03-29
        相关资源
        最近更新 更多