Silverlight DataGrid 获取 Row 左键双击事件

今天需要做 DataGrid 双击后弹出一个窗口的功能。突然发现 DataGrid 这东西很蛋疼,本身不支持也就罢了,还有更恶心的。比如 DataGrid 不能被继承,再比如 DataGridCell 中 Handle 了 MouseLeftButtonDown 事件。

于是,只好走点弯路。自己创建了一个 DataGridHelper

namespace SoftCat.Windows.Controls
{
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;

    public class DataGridHelper
    {
        // ===================================================================
        // 字段

        DataGrid _dg;

        // ===================================================================
        // 构造与析构

        public DataGridHelper(DataGrid dg)
        {
            _dg = dg;

            _dg.LoadingRow += _dg_LoadingRow;
        }

        // ===================================================================
        // 事件处理

        void _dg_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.Loaded += Row_Loaded;
        }

        private void Row_Loaded(object sender, RoutedEventArgs e)
        {
            DataGridRow row = sender as DataGridRow;

            foreach (DataGridCell cell in VisualTreeHelperEx.FindChildren<DataGridCell>(row))
            {
                Grid cellGrid = VisualTreeHelper.GetChild(cell, 0) as Grid;
                cellGrid.MouseLeftButtonDown += cellGrid_MouseLeftButtonDown;
            }
        }

        private void cellGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (RowMouseLeftButtonDown == null && CellMouseLeftButtonDown == null) return;

            Grid cellGrid = sender as Grid;
            DataGridCell cell = VisualTreeHelper.GetParent(cellGrid) as DataGridCell;

            if (CellMouseLeftButtonDown != null)
                CellMouseLeftButtonDown(cell, e);

            if (RowMouseLeftButtonDown != null)
            {
                DataGridRow row = VisualTreeHelperEx.FindParent<DataGridRow>(cell);
                RowMouseLeftButtonDown(row, e);
            }
        }

        // ===================================================================
        // 扩展事件

        public event MouseButtonEventHandler RowMouseLeftButtonDown;

        public event MouseButtonEventHandler CellMouseLeftButtonDown;

    }
}

上面的这段代码为了突出重点,省去了左键 Up 和右键事件,需要者可以自行添加。

请注意,DataGridCell 的子节点是一个 Grid,我们通过这个 Grid 的 MouseLeftButtonDown 事件捕获到我们需要的行为,然后再转嫁给 DataGridCell 和 DataGridRow。

这是一种投机取巧的行为,但不失为一种万不得已的方法。

此外,上面的代码中使用了我自己写的 VisualTreeHelperEx,代码如下。

namespace SoftCat.Windows
{
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Media;

    public static class VisualTreeHelperEx
    {
        public static IEnumerable<T> FindChildren<T>(DependencyObject reference) where T : DependencyObject
        {
            if (reference == null) throw new ArgumentNullException();

            Queue<DependencyObject> q = new Queue<DependencyObject>();

            int c = VisualTreeHelper.GetChildrenCount(reference);

            for (int i = 0; i < c; i++)
            {
                DependencyObject o = VisualTreeHelper.GetChild(reference, i);
                q.Enqueue(o);
            }

            while (q.Count > 0)
            {
                DependencyObject r = q.Dequeue();

                if (r is T)
                {
                    yield return r as T;
                }
                else
                {
                    c = VisualTreeHelper.GetChildrenCount(r);

                    for (int i = 0; i < c; i++)
                    {
                        DependencyObject o = VisualTreeHelper.GetChild(r, i);
                        q.Enqueue(o);
                    }
                }
            }
        }

        public static T FindParent<T>(DependencyObject reference) where T : DependencyObject
        {
            if (reference == null) throw new ArgumentNullException();

            DependencyObject p = reference;

            do
            {
                p = VisualTreeHelper.GetParent(p);

                if (p is T)
                {
                    return p as T;
                }
            }
            while (p != null);

            return null;
        }

    }
}

希望这篇文章能给您带来一些小小的启发。如果有更好的方法还请告知,谢谢!

原文地址:https://www.cnblogs.com/softcat/p/2788230.html