还有的时候,会遇到DataGrid里面嵌套DataGrid(重叠嵌套),然后里面的鼠标滚轮无法响应外面的滚动,为此记录下解决方案

与上一篇区别在于,详情里面的模板通常是通用的,被定义在样式文件中,被重复使用,因此无法为其添加后台代码,如果能添加后台代码,请翻阅第一篇;所以需要用到命令的方式来辅助事件的抛出,当然还可以利用第三方库Prism,他可以把事件当命令传递,且能传递事件的默认参数,详情请参阅这篇文章;好了,下面开始介绍,扩展DataGrid类,通过自定义命令抛出事件,并传递事件参数...

先请大致看下运行效果:

下面是详情代码,尾部有完整demo,下载

 1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 2                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 3                     xmlns:local="clr-namespace:CustomCommand">
 4 
 5     <Style TargetType="DataGrid">
 6         <Setter Property="IsReadOnly" Value="True" />
 7         <Setter Property="CanUserAddRows" Value="False" />
 8         <Setter Property="CanUserDeleteRows" Value="False" />
 9         <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
10     </Style>
11     
12     <!--为了不影响已设置的最基础样式,所以下面这个集成样式很重要-->
13     <Style TargetType="local:CustomDataGrid" BasedOn="{StaticResource {x:Type DataGrid}}" />
14 
15     <DataTemplate x:Key="RowDetails">
16         <local:CustomDataGrid ItemsSource="{Binding Infos}" 
17                               MouseWheelCommand="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window},Path=MouseWheelCommand}" />
18     </DataTemplate>
19 </ResourceDictionary>
特别标注下,需要继承默认样式,否则应用到项目中,会区别出异样的
<!--为了不影响已设置的最基础样式,所以下面这个集成样式很重要--> <Style TargetType="local:CustomDataGrid" BasedOn="{StaticResource {x:Type DataGrid}}" />
 1 using Prism.Commands;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Collections.ObjectModel;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 using System.Windows;
 9 using System.Windows.Controls;
10 using System.Windows.Data;
11 using System.Windows.Documents;
12 using System.Windows.Input;
13 using System.Windows.Media;
14 using System.Windows.Media.Imaging;
15 using System.Windows.Navigation;
16 using System.Windows.Shapes;
17 
18 namespace CustomCommand
19 {
20     /// <summary>
21     /// MainWindow.xaml 的交互逻辑
22     /// </summary>
23     public partial class MainWindow : Window
24     {
25         /// <summary>
26         /// 鼠标滚动时发送
27         /// </summary>
28         public ICommand MouseWheelCommand { get; private set; }
29 
30         public ObservableCollection<Info> Datas = new ObservableCollection<Info>();
31 
32         public MainWindow()
33         {
34             MouseWheelCommand = new DelegateCommand<object>(CustomMouseWheel);
35 
36             InitializeComponent();
37             datagrid.ItemsSource = Datas;
38 
39             for (int i = 0; i < 50; i++)
40             {
41                 var info = new Info();
42                 info.name = "第一级" + i;
43                 Datas.Add(info);
44 
45                 if (i % 2 == 0)
46                 {
47                     for (int j = 0; j < 20; j++)
48                     {
49                         info.Infos.Add(new Info()
50                         {
51                             name = "第二级" + j
52                         });
53                     }
54                 }
55             }
56         }
57 
58 
59         /// <summary>
60         /// 当DataGrid的详情行里的DataGrid滚动时发生
61         /// </summary>
62         /// <param name="obj"></param>
63         void CustomMouseWheel(object p)
64         {
65             if (p is MouseWheelEventArgs e)
66             {
67                 var sc = GetVisualChild<ScrollViewer>(datagrid);
68                 if (sc != null)
69                 {
70                     sc.ScrollToVerticalOffset(sc.VerticalOffset - e.Delta);
71                 }
72             }
73         }
74 
75         T GetVisualChild<T>(Visual parent) where T : Visual
76         {
77             T child = default(T);
78             int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
79             for (int i = 0; i < numVisuals; i++)
80             {
81                 var v = (Visual)VisualTreeHelper.GetChild(parent, i);
82                 child = v as T ?? GetVisualChild<T>(v);
83                 if (child != null)
84                     break;
85             }
86             return child;
87         }
88     }
89 
90     public class Info
91     {
92         public string name { get; set; }
93 
94         public ObservableCollection<Info> Infos { get; set; } = new ObservableCollection<Info>();
95     }
96 }
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Input;
 9 
10 namespace CustomCommand
11 {
12     /// <summary>
13     /// 自定义扩展DataGrid  主要是用于响应滚轮事件
14     /// </summary>
15     public class CustomDataGrid : DataGrid
16     {
17         public CustomDataGrid()
18         {
19             PreviewMouseWheel += CustomDataGrid_PreviewMouseWheel;
20         }
21 
22         /// <summary>
23         /// 鼠标滚动滚动时
24         /// </summary>
25         /// <param name="sender"></param>
26         /// <param name="e"></param>
27         private void CustomDataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
28         {
29             MouseWheelCommand?.Execute(e);//触发命令,并把MouseWheelEventArgs传递
30         }
31 
32         /// <summary>
33         /// 声明一个用于滚动通知的命令
34         /// </summary>
35         public ICommand MouseWheelCommand
36         {
37             get { return (ICommand)GetValue(MouseWheelCommandProperty); }
38             set { SetValue(MouseWheelCommandProperty, value); }
39         }
40 
41         public static readonly DependencyProperty MouseWheelCommandProperty =
42             DependencyProperty.Register("MouseWheelCommand", typeof(ICommand), typeof(CustomDataGrid), new PropertyMetadata(default(ICommand)));
43 
44     }
45 }

下面是完整demo,有需要的可以下载

原文地址:https://www.cnblogs.com/xuling-297769461/p/12761513.html