katit
katit

Reputation: 17905

Silverlight 5 double-click always returns ClickCount as 1

I created behavior for DataGrid to detect double-click:

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);
        }
    }

Everything seems to be fine except that it doesn't register multiple clicks. In OnMouseLeftButtonUp ClickCount always 1. Does anybody know why?

Upvotes: 8

Views: 5333

Answers (5)

herzmeister
herzmeister

Reputation: 11287

I found a very simple solution. Just replace the event handler registration syntax

myDataGrid.MouseLeftButtonDown += this.MyDataGrid_MouseLeftButtonDown;

with the AddHandler syntax

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

That way the magic boolean handledEventsToo argument can be specified.

This will, well, handle handled events too.

Upvotes: 11

Jeff
Jeff

Reputation: 36573

MouseButtonUp is broken with respect to capturing ClickCount in WPF and Silverlight (it's been recorded many times but Microsoft has opted not to fix it). You need to use MouseButtonDown events.

Upvotes: 1

Duncan Matheson
Duncan Matheson

Reputation: 1726

I ran into this exact same problem. I couldn't manage to resolve it in any sensible way, so worked around it like this:

    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);
    }

It's dirty but it works.

Upvotes: 0

Doguhan Uluca
Doguhan Uluca

Reputation: 7323

Well, the bigger trouble here is that when you click on the rows of a DataGrid, MouseLeftButtonDown is not raised, because this click is being handled at the row level.

I've long given up on dealing with some controls directly. I've my own derived version of the DataGrid, DataForm and etc. This only makes my solution easy to roll out, because I don't use the vanilla versions anyway.

I added a new event called ClickIncludingHandled, it's a bit wordy but it properly describes what's going on and will nicely appear right below Click with IntelliSense - if the control has a Click event to begin with.

Anyway, below is my implementation of it. You can then subscribe to this event and use ClickCount to determine the number of clicks you want to capture. I noticed it is a bit slow, but it works cleanly.

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);
            }
        }
}

Upvotes: 3

James Manning
James Manning

Reputation: 13579

Not 100% sure this is the issue, but I notice that Pete Brown's sample uses MouseLeftButtonDown instead:

http://10rem.net/blog/2011/04/13/silverlight-5-supporting-double-and-even-triple-click-for-the-mouse

Upvotes: 0

Related Questions