有的时候,会遇到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 }
有需要源码运行的也可以下载!