Saturday, January 5, 2013

Double Click Beheaver of Data Grid Control

//Add First Class

public class DataGridDoubleClickBehavior : Behavior<System.Windows.Controls.DataGrid>
    {
       private readonly MouseClickManager _gridClickManager;
        public event EventHandler<MouseButtonEventArgs> DoubleClick;

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

        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(DataGridDoubleClickBehavior), new PropertyMetadata(CommandParameterChanged));

        private static void CommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // Code for dealing with your property changes
        }
        public ICommand DoubleClickCommand
        {
            get { return (ICommand)GetValue(DoubleClickCommandProperty); }
            set { SetValue(DoubleClickCommandProperty, value); }
        }

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

        private static void DoubleClickCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // Code for dealing with your property changes
        }

        public DataGridDoubleClickBehavior()
        {
            _gridClickManager = new MouseClickManager(300);
            _gridClickManager.DoubleClick += new MouseButtonEventHandler(_gridClickManager_DoubleClick);
        }

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

        void OnUnloadingRow(object sender, DataGridRowEventArgs e)
        {
            //row is no longer visible so remove double click event otherwise
            //row events will miss fire
            e.Row.MouseLeftButtonUp -= _gridClickManager.HandleClick;
        }

        void OnLoadingRow(object sender, DataGridRowEventArgs e)
        {
            //row is visible in grid, wire up double click event
            e.Row.MouseLeftButtonUp += _gridClickManager.HandleClick;
        }

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

        void _gridClickManager_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (DoubleClick != null)
                DoubleClick(sender, e);

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

    }

//Add Second Class

public class MouseClickManager
    {

        #region Private members

        private event MouseButtonEventHandler _click;

        private event MouseButtonEventHandler _doubleClick;

        #endregion

        #region Constructor

        /// <summary>

        /// Initializes a new instance of the <see cref="MouseClickManager"/> class.

        /// </summary>

        /// <param name="control">The control.</param>

        public MouseClickManager(int doubleClickTimeout)
        {

            this.Clicked = false;

            this.DoubleClickTimeout = doubleClickTimeout;

        }

        #endregion

        #region Events

        public event MouseButtonEventHandler Click
        {

            add { _click += value; }

            remove { _click -= value; }

        }

        public event MouseButtonEventHandler DoubleClick
        {

            add { _doubleClick += value; }

            remove { _doubleClick -= value; }

        }

        /// <summary>

        /// Called when [click].

        /// </summary>

        /// <param name="sender">The sender.</param>

        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>

        private void OnClick(object sender, MouseButtonEventArgs e)
        {

            if (_click != null)
            {

                Debug.Assert(sender is Control);

                (sender as Control).Dispatcher.BeginInvoke(_click, sender, e);

            }

        }

        /// <summary>

        /// Called when [double click].

        /// </summary>

        /// <param name="sender">The sender.</param>

        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>

        private void OnDoubleClick(object sender, MouseButtonEventArgs e)
        {

            if (_doubleClick != null)
            {

                _doubleClick(sender, e);

            }

        }

        /// <summary>

        /// Handles the click.

        /// </summary>

        /// <param name="sender">The sender.</param>

        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>

        public void HandleClick(object sender, MouseButtonEventArgs e)
        {

            lock (this)
            {

                if (this.Clicked)
                {

                    this.Clicked = false;

                    OnDoubleClick(sender, e);

                }

                else
                {

                    this.Clicked = true;

                    ParameterizedThreadStart threadStart = new ParameterizedThreadStart(ResetThread);

                    Thread thread = new Thread(threadStart);

                    thread.Start(e);

                }

            }

        }

        #endregion

        #region Properties

        /// <summary>

        /// Gets or sets a value indicating whether this <see cref="MouseClickManager"/> is clicked.

        /// </summary>

        /// <value><c>true</c> if clicked; otherwise, <c>false</c>.</value>

        private bool Clicked { get; set; }

        /// <summary>

        /// Gets or sets the timeout.

        /// </summary>

        /// <value>The timeout.</value>

        public int DoubleClickTimeout { get; set; }

        #endregion

        #region Methods

        #region Private

        /// <summary>

        /// Resets the thread.

        /// </summary>

        /// <param name="state">The state.</param>

        private void ResetThread(object state)
        {

            Thread.Sleep(this.DoubleClickTimeout);



            lock (this)
            {

                if (this.Clicked)
                {

                    this.Clicked = false;

                    OnClick(this, (MouseButtonEventArgs)state);

                }

            }

        }

        #endregion

        #endregion


    }
//and final use into xaml page
When we will use this behaviour then follow steps
1. add  reference
2. add behevoiur into grid


<sdk:DataGrid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"                                        
                            Name="DgReqForPo"                        
                            ItemsSource="{Binding Path=ReqPvList, Mode=TwoWay}"                      
                            ColumnWidth="*"
                            ColumnHeaderStyle="{StaticResource DGRmvdSortIconStyle}"
                            AutoGenerateColumns="False"
                            VerticalAlignment="Top"                      
                            IsReadOnly="True"    
                            IsTabStop="False"
                            CanUserReorderColumns="False"
                            CanUserResizeColumns="False"
                            CanUserSortColumns="False"                      
                            GridLinesVisibility="All"
                            HorizontalScrollBarVisibility="Hidden"
                            SelectionMode="Single">                          
                                <sdk:DataGridTextColumn Binding="{Binding Path=BuyerName}" Header="Buyer"/>
                                <sdk:DataGridTextColumn Binding="{Binding Path=Order}" Header="OrderNo"/>
                                <sdk:DataGridTextColumn Binding="{Binding Path=Style}" Header="Style"/>                                                            </sdk:DataGrid.Columns>
                            <i:Interaction.Behaviors>
                                <lib:DataGridDoubleClickBehavior DoubleClickCommand="{Binding DoubleCommand}"
                                                                 CommandParameter="{Binding SelectedItem,ElementName=DgReqForPo}"/>
                            </i:Interaction.Behaviors>
                        </sdk:DataGrid>


2 comments:

  1. void _gridClickManager_DoubleClick(object sender, MouseButtonEventArgs e)
    {
    if (DoubleClick != null)
    DoubleClick(sender, e);

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

    // i get DoubleClickCommand = null on double click, it didn't go to view model to get value from the property bound to the DoubleClickCommand.

    ReplyDelete
  2. I got your problem. you can use static resource as a source of command binding

    ReplyDelete