還有的時候,會遇到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,有需要的可以下載

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章