zoukankan      html  css  js  c++  java
  • 有的时候,会遇到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 }

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

  • 相关阅读:
    uboot的仓库在哪里?
    git如何查看执行过的历史git命令
    for(;;)和while(true)的区别
    CountDownLatch的理解和使用
    countDownLatch
    websocket @ServerEndpoint(value = "/websocket/{ip}")详解
    Java原子性操作之——Atomic包的原理分析
    CAS原理
    java线程池ThreadPoolExecutor的keepAliveTime=0时,表示超过core线程数的线程在空闲时立即结束!!!
    ThreadPoolExecutor 线程池Demo
  • 原文地址:https://www.cnblogs.com/xuling-297769461/p/12744920.html
Copyright © 2011-2022 走看看