zoukankan      html  css  js  c++  java
  • Silverlight中在MVVM模式下对DatagridRow选择控件封装

      在项目中,凡是涉及到表格的地方用的最多的控件,自然少不了DataGrid的身影,它明了的展示各种数据让人十分喜欢。现在要实现一个功能,使DataGrid具有全选和项选中的功能,如果在传统后台代码中完成这个事情可以说十分简单,但是换到MVVM模式下呢? 不得不面临一个很囧的情况,为了完成UI端CheckBox被选中后能在ViewModel中获取到选中的数据,不得不在在业务实体之外添加一个字段IsChecked 来与我们的数据交互,这样不仅影响美观还影响心情。

      为了实现这一点,无疑需要设置DataGridTemplateColumn的CellTemplate,同时让每一个checkBox拥有这条数据的上下文引用,已方便在当我们选中或反选时能确定数据项,最好的设置时机当然是DataGrid的LoadingRow事件,可以捕获到我们所需要的一切。

      当然,为了实现MVVM,我们需要添加一下附加属性

     1 public static ObservableCollection<object> GetSelectedObjects(DependencyObject obj)
     2         {
     3             return (ObservableCollection<object>)obj.GetValue(SelectedObjectsProperty);
     4         }
     5 
     6         public static void SetSelectedObjects(DependencyObject obj, ObservableCollection<object> value)
     7         {
     8             obj.SetValue(SelectedObjectsProperty, value);
     9         }
    10       
    11         // 用于通知到ViewModel已经被选中的列
    12         public static readonly DependencyProperty SelectedObjectsProperty =
    13             DependencyProperty.RegisterAttached("SelectedObjects", typeof(ObservableCollection<object>), typeof(DataGrid), new PropertyMetadata(new ObservableCollection<object>()));
    14 
    15         public static bool GetMonitor(DependencyObject obj)
    16         {
    17             return (bool)obj.GetValue(MonitorProperty);
    18         }
    19 
    20         public static void SetMonitor(DependencyObject obj, bool value)
    21         {
    22             obj.SetValue(MonitorProperty, value);
    23         }
    24 
    25         // 监视器,用于在DataGrid初始化的时候能有时机注册LoadingRow事件
    26         public static readonly DependencyProperty MonitorProperty =
    27             DependencyProperty.RegisterAttached("Monitor", typeof(bool), typeof(DataGrid), new PropertyMetadata(false, OnMonitorStateChanged));
    28 
    29         private static void OnMonitorStateChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
    30         {
    31             var attachedDataGrid = dp as DataGrid;
    32             _attachedDataGrid = attachedDataGrid;
    33             _attachedDataGrid.LoadingRow += (s, ee) =>
    34             {
    35                 object dataContext = ee.Row.DataContext;
    36                 var elementControl = _attachedDataGrid.Columns[0] as DataGridSelectableColumn;
    37                 if (elementControl == null)
    38                     throw new InvalidCastException("请将DataGridSelectableColumn放在DataGrid的第一列");
    39                 FrameworkElement element = elementControl.GetCellContent(ee.Row);
    40 
    41                 var elementContext = new SelectableColumnObject() {RowDataContext = new WeakReference( dataContext) };
               //当CheckBox的IsChecked属性值变化之后发生
    42 elementContext.OnChildItemStateChanged += elementContext_OnChildItemStateChanged; 43 element.DataContext = elementContext; 44 45 }; 46 } 47 48 static void elementContext_OnChildItemStateChanged(WeakReference rowDataContext, bool obj) 49 { 50 _currentColumn.UpdateChildItemSelectedState(rowDataContext, obj); 51 }

      我将这一列的数据上下文保存到了一个名为RowDataContext的字段中,这样就满足了当选择状态更新时我能知道是那条数据,那么剩下的工作就是列选择和全选状态更新的事件了。Silverlight中DataGrid没有HeaderTemplate,也没有其他事件能够帮助我知道Header的加载,这时候需要借助于xaml,如下

     1     <sdk:DataGridTemplateColumn.HeaderStyle>
     2         <Style TargetType="sdk:DataGridColumnHeader">
     3             <Setter Property="Padding" Value="4" />
     4             <Setter Property="Template">
     5                 <Setter.Value>
     6                     <ControlTemplate TargetType="sdk:DataGridColumnHeader">
     7                         <CheckBox VerticalAlignment="Center"  HorizontalAlignment="Center" VerticalContentAlignment="Center" Content="全选" Loaded="OnHeaderCheckBoxLoaded" />
     8                     </ControlTemplate>
     9                 </Setter.Value>
    10             </Setter>
    11         </Style>
    12     </sdk:DataGridTemplateColumn.HeaderStyle>

      有了这里我们就可以直接在后台代码中定义事件进行处理

     private void OnHeaderCheckBoxLoaded(object sender, RoutedEventArgs e)
            {
                var checkBox = sender as CheckBox;
                if (checkBox == null)
                    return;
    
                checkBox.Loaded -= this.OnHeaderCheckBoxLoaded;
                checkBox.Checked += (s2, e2) => this.UpdateAllItemSelectedState(true);
                checkBox.Unchecked += (s2, e2) => this.UpdateAllItemSelectedState(false);
            }

      到此为止,我们要做的工作基本已经完工,全选状态、行数据的选择状态更新我们做相应处理了。

    源码下载:Silverlight下MVVM全选控件_无需额外添加字段.zip

  • 相关阅读:
    利用python脚本统计和删除redis key
    利用expect交互完成多台linux主机ssh key推送
    iptables -L很慢的原因
    tomcat各个端口的作用
    rabbitmq集群搭建
    ping 没有回icmp reply
    go mod 无法下载依赖问题
    0/1 nodes are available: 1 node(s) had taint
    go 编译:build constraints exclude all Go files in
    k8s单机部署
  • 原文地址:https://www.cnblogs.com/zeoy/p/3732268.html
Copyright © 2011-2022 走看看