将行的双击绑定到Silverlight数据网格中的命令

时间:2010-01-21 03:22:59

标签: silverlight datagrid

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

2 个答案:

答案 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>

没有运气。