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

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

本实例是在DataGrid的详情行里再嵌入一个DataGrid,模拟重叠的情况,先看下效果,当然效果是不理想的

再看下优化的效果,可见效果明显,如果您有更优越的方式请勿喷,本人能力有限,也是参照网上的,特此整理下:

 

好了,效果看完,我主要说明下:

原理就是采用滚动方式为像素,捕获里面的DataGrid的鼠标滚轮事件,再获取到外部的DataGrid的ScrollViewer对象,将滚动的量设置给ScrollViewer即可

下面是详细代码:

 1 <Window x:Class="DataGridDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:DataGridDemo"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="500">
 9     <Window.Resources>
10         <Style TargetType="DataGrid">
11             <Setter Property="AutoGenerateColumns" Value="False" />
12             <Setter Property="CanUserAddRows" Value="False" />
13             <Setter Property="IsReadOnly" Value="True" />
14             <Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel"/>
15         </Style>
16         <DataTemplate x:Key="DataDetailsTemplate">
17             <DataGrid ItemsSource="{Binding Subs}" PreviewMouseWheel="DataGrid_PreviewMouseWheel" >
18                 <DataGrid.Columns>
19                     <DataGridTextColumn Header="详情名称" Binding="{Binding Name}" />
20                 </DataGrid.Columns>
21             </DataGrid>
22         </DataTemplate>
23     </Window.Resources>
24     <Grid>
25         <DataGrid x:Name="data" RowDetailsTemplate="{StaticResource DataDetailsTemplate}">
26             <DataGrid.Columns>
27                 <DataGridTextColumn Header="名称" Binding="{Binding Name}" />
28             </DataGrid.Columns>
29         </DataGrid>
30     </Grid>
31 </Window>
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Collections.ObjectModel;
  4 using System.ComponentModel;
  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 DataGridDemo
 19 {
 20     /// <summary>
 21     /// MainWindow.xaml 的交互逻辑
 22     /// </summary>
 23     public partial class MainWindow : Window
 24     {
 25         public ObservableCollection<Info> Data = new ObservableCollection<Info>();
 26 
 27         public MainWindow()
 28         {
 29             InitializeComponent();
 30 
 31             data.ItemsSource = Data;
 32 
 33             for (int i = 0; i < 50; i++)
 34             {
 35                 ObservableCollection<Info> Subs = null;
 36                 if (i == 1)
 37                 {
 38                     Subs = new ObservableCollection<Info>();
 39                     for (int j = 0; j < 100; j++)
 40                     {
 41                         Subs.Add(new Info() { Name = "子项" + j });
 42                     }
 43                 }
 44                 Data.Add(new Info() { Name = "测试" + i, Subs = Subs });
 45             }
 46         }
 47 
 48         /// <summary>
 49         /// 详情里面的datagrid,鼠标滚轮滚动时
 50         /// </summary>
 51         /// <param name="sender"></param>
 52         /// <param name="e"></param>
 53         private void DataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
 54         {
 55             //特别提示:因为这里需要寻找指定的DataGrid的ScrollViewer,如果此处无法获取到DataGrid,可以利用FindVisualParent匹配出符合的父级进行操作
 56             if (sender is DataGrid grid && data == null)
 57             {
 58                 var gs = FindVisualParent<DataGrid>(grid);
 59                 data = gs.Where(c => c.Name.Equals("控件name")).FirstOrDefault();
 60             }
 61 
 62             var sc = GetVisualChild<ScrollViewer>(data);
 63 
 64             if (sc != null)
 65             {
 66                 sc.ScrollToVerticalOffset(sc.VerticalOffset - e.Delta);
 67             }
 68         }
 69 
 70         //匹配返回符合条件的子控件
 71         T GetVisualChild<T>(Visual parent) where T : Visual
 72         {
 73             T child = default(T);
 74             int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
 75             for (int i = 0; i < numVisuals; i++)
 76             {
 77                 var v = (Visual)VisualTreeHelper.GetChild(parent, i);
 78                 child = v as T ?? GetVisualChild<T>(v);
 79                 if (child != null)
 80                     break;
 81             }
 82             return child;
 83         }
 84 
 85         //匹配返回符合条件的所有子控件
 86         IEnumerable<T> FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
 87         {
 88             try
 89             {
 90                 List<T> TList = new List<T> { };
 91                 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
 92                 {
 93                     DependencyObject child = VisualTreeHelper.GetChild(obj, i);
 94                     if (child != null && child is T)
 95                     {
 96                         TList.Add((T)child);
 97                         IEnumerable<T> childOfChildren = FindVisualChild<T>(child);
 98                         if (childOfChildren != null)
 99                         {
100                             TList.AddRange(childOfChildren);
101                         }
102                     }
103                     else
104                     {
105                         IEnumerable<T> childOfChildren = FindVisualChild<T>(child);
106                         if (childOfChildren != null)
107                         {
108                             TList.AddRange(childOfChildren);
109                         }
110                     }
111                 }
112                 return TList;
113             }
114             catch (Exception ee)
115             {
116                 MessageBox.Show(ee.Message);
117                 return null;
118             }
119         }
120 
121         //匹配返回符合条件的父控件
122         T GetVisualParent<T>(DependencyObject child) where T : Visual
123         {
124             DependencyObject parentObject = VisualTreeHelper.GetParent(child);
125 
126             if (parentObject == null)
127             {
128                 return null;
129             }
130 
131             T parent = parentObject as T;
132             if (parent != null)
133             {
134                 return parent;
135             }
136             else
137             {
138                 return GetVisualParent<T>(parentObject);
139             }
140         }
141 
142         //匹配返回符合条件的所有父控件
143         IEnumerable<T> FindVisualParent<T>(DependencyObject obj) where T : DependencyObject
144         {
145             try
146             {
147                 List<T> TList = new List<T> { };
148                 DependencyObject parent = VisualTreeHelper.GetParent(obj);
149                 if (parent != null && parent is T)
150                 {
151                     TList.Add((T)parent);
152                     IEnumerable<T> parentOfParent = FindVisualParent<T>(parent);
153                     if (parentOfParent != null)
154                     {
155                         TList.AddRange(parentOfParent);
156                     }
157                 }
158                 else if (parent != null)
159                 {
160                     IEnumerable<T> parentOfParent = FindVisualParent<T>(parent);
161                     if (parentOfParent != null)
162                     {
163                         TList.AddRange(parentOfParent);
164                     }
165                 }
166                 return TList;
167             }
168             catch (Exception ee)
169             {
170                 MessageBox.Show(ee.Message);
171                 return null;
172             }
173         }
174     }
175 
176     public class Info
177     {
178         public string Name { get; set; }
179 
180         public ObservableCollection<Info> Subs { get; set; }
181     }
182 }

 

有需要源码运行的也可以下载

posted @ 2020-04-21 16:10  吃奶嘴的路飞  阅读(297)  评论(0编辑  收藏  举报