Silverlight 5双击操作始终返回ClickCount为1。

8

我为DataGrid创建了一个行为,以便检测双击:

public class DataGridDoubleClickBehavior : Behavior<DataGrid>    
    {
        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
            "CommandParameter",
            typeof(object),
            typeof(DataGridDoubleClickBehavior),
            new PropertyMetadata(null));        

        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }            
            set { SetValue(CommandParameterProperty, value); }
        }

        public static readonly DependencyProperty DoubleClickCommandProperty = DependencyProperty.Register(
            "DoubleClickCommand",
            typeof(ICommand),
            typeof(DataGridDoubleClickBehavior),
            new PropertyMetadata(null));       

        public ICommand DoubleClickCommand
        {
            get { return (ICommand)GetValue(DoubleClickCommandProperty); }            
            set { SetValue(DoubleClickCommandProperty, value); }
        }

        protected override void OnAttached()
        {
            this.AssociatedObject.LoadingRow += this.OnLoadingRow;
            this.AssociatedObject.UnloadingRow += this.OnUnloadingRow;

            base.OnAttached();
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.LoadingRow -= this.OnLoadingRow;
            this.AssociatedObject.UnloadingRow -= this.OnUnloadingRow;

            base.OnDetaching();
        } 

        private void OnLoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp += this.OnMouseLeftButtonUp;
        }

        private void OnUnloadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp -= this.OnMouseLeftButtonUp;
        }

        private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount < 2) return;

            if (this.DoubleClickCommand != null) this.DoubleClickCommand.Execute(this.CommandParameter);
        }
    }

除了无法注册多次点击之外,一切似乎都很正常。在 OnMouseLeftButtonUp 中 ClickCount 总是 1。有人知道为什么吗?


作为一些健全性检查,也许可以运行Pete的示例来验证其是否有效,或者运行现有的SL4 DataGrid+DoubleClick项目之一,如http://www.codeproject.com/Articles/115405/Double-Click-DataGrid-in-Silverlight? - James Manning
我所做的是 SL5 升级的一部分。由于多次点击实际上是“支持”的,因此要摆脱那样的代码... 我有可用的代码。我只想让它正确。 - katit
5个回答

11

我发现了一个非常简单的解决方案。只需替换事件处理程序注册语法即可。

myDataGrid.MouseLeftButtonDown += this.MyDataGrid_MouseLeftButtonDown;

使用AddHandler语法

myDataGrid.AddHandler(DataGrid.MouseLeftButtonDownEvent,
    new MouseButtonEventHandler(this.MyDataGrid_MouseLeftButtonDown),
    handledEventsToo: true)

这样可以指定一个神奇的布尔型参数handledEventsToo

这将处理已处理过的事件。


这个很好地运作了 :-) 然后使用交互性的东西将事件传递到 VM,你就成功了。 - Shane Neuville
对我有用并且给了+1。你不必在那里加上handledEventsToo:,但我想这也没有什么坏处。 - McAden
1
在方法调用时,使用字面量(如true42)而不是描述性变量来指定参数是一个好的编程实践。这样可以使代码更易读。 - herzmeister

3

问题在于,当你单击DataGrid的行时,MouseLeftButtonDown不会被触发,因为这个点击事件在行级别上被处理了。

我已经放弃直接处理某些控件了。我有自己派生的版本的DataGrid、DataForm等等。这只是使我的解决方案易于推出,因为我根本不使用原始版本。

我添加了一个新事件叫做ClickIncludingHandled,它有点啰嗦,但它恰当地描述了正在发生的事情,并将与Click一起很好地出现在IntelliSense下面——如果控件本来就有Click事件的话。

无论如何,下面是我的实现。然后你可以订阅这个事件并使用ClickCount来确定你想要捕获的点击次数。我注意到它有点慢,但它工作得很干净。

public partial class DataGridBase : DataGrid
{
        public event MouseButtonEventHandler ClickIncludingHandled;

        public DataGridBase() : base()
        {
            this.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnClickInclHandled), true);
        }

        private void OnClickInclHandled(object sender, MouseButtonEventArgs e)
        {
            if (ClickIncludingHandled != null)
            {
                ClickIncludingHandled(sender, e);
            }
        }
}

1

在 WPF 和 Silverlight 中,MouseButtonUp 在捕获 ClickCount 方面存在问题(这个问题已经被记录了很多次,但微软选择不修复它)。您需要使用 MouseButtonDown 事件。


0

0

我也遇到了同样的问题。我无法以任何明智的方式解决它,所以我像这样解决了它:

    private DateTime _lastClickTime;
    private WeakReference _lastSender;

    private void Row_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        var now = DateTime.Now;
        if ((now - _lastClickTime).TotalMilliseconds < 200 && _lastSender != null && _lastSender.IsAlive && _lastSender.Target == sender)
        {
            if (Command != null)
            {
                Command.Execute(CommandParameter);
            }
        }
        _lastClickTime = now;
        _lastSender = new WeakReference(sender);
    }

虽然有点脏,但它能用。


从技术上讲,应该使用SystemInformation.DoubleClickTime,并检查每个点击是否在SystemInformation.DoubleClickSize范围内。 - EricLaw
SystemInformation类位于System.Windows.Forms中,因此在Silverlight中不可用。 - Duncan Matheson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接