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

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

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

 public static ObservableCollection<object> GetSelectedObjects(DependencyObject obj)
{
return (ObservableCollection<object>)obj.GetValue(SelectedObjectsProperty);
} public static void SetSelectedObjects(DependencyObject obj, ObservableCollection<object> value)
{
obj.SetValue(SelectedObjectsProperty, value);
}
      
// 用于通知到ViewModel已经被选中的列
public static readonly DependencyProperty SelectedObjectsProperty =
DependencyProperty.RegisterAttached("SelectedObjects", typeof(ObservableCollection<object>), typeof(DataGrid), new PropertyMetadata(new ObservableCollection<object>())); public static bool GetMonitor(DependencyObject obj)
{
return (bool)obj.GetValue(MonitorProperty);
} public static void SetMonitor(DependencyObject obj, bool value)
{
obj.SetValue(MonitorProperty, value);
} // 监视器,用于在DataGrid初始化的时候能有时机注册LoadingRow事件
public static readonly DependencyProperty MonitorProperty =
DependencyProperty.RegisterAttached("Monitor", typeof(bool), typeof(DataGrid), new PropertyMetadata(false, OnMonitorStateChanged)); private static void OnMonitorStateChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
var attachedDataGrid = dp as DataGrid;
_attachedDataGrid = attachedDataGrid;
_attachedDataGrid.LoadingRow += (s, ee) =>
{
object dataContext = ee.Row.DataContext;
var elementControl = _attachedDataGrid.Columns[] as DataGridSelectableColumn;
if (elementControl == null)
throw new InvalidCastException("请将DataGridSelectableColumn放在DataGrid的第一列");
FrameworkElement element = elementControl.GetCellContent(ee.Row); var elementContext = new SelectableColumnObject() {RowDataContext = new WeakReference( dataContext) };
           //当CheckBox的IsChecked属性值变化之后发生
elementContext.OnChildItemStateChanged += elementContext_OnChildItemStateChanged;
element.DataContext = elementContext; };
} static void elementContext_OnChildItemStateChanged(WeakReference rowDataContext, bool obj)
{
_currentColumn.UpdateChildItemSelectedState(rowDataContext, obj);
}

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

     <sdk:DataGridTemplateColumn.HeaderStyle>
<Style TargetType="sdk:DataGridColumnHeader">
<Setter Property="Padding" Value="" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridColumnHeader">
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" VerticalContentAlignment="Center" Content="全选" Loaded="OnHeaderCheckBoxLoaded" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</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

Silverlight中在MVVM模式下对DatagridRow选择控件封装的更多相关文章

  1. Atitit.ui控件---下拉菜单选择控件的实现select html

    Atitit.ui控件---下拉菜单选择控件的实现select   html 1. 调用& model的实现 1 2. -----select.jsp------ 1 1. 调用& m ...

  2. WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题

    问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...

  3. 关于使用MVVM模式在WPF的DataGrid控件中实现ComboBox编辑列

    最近在做一个组态软件的项目,有一个需求需要在建立IO设备变量的时候选择变量的类型等. 建立IO变量的界面是一个DataGrid实现的,可以一行一行的新建变量,如下如所示: 这里需要使用带有ComboB ...

  4. angular中的MVVM模式

    在开始介绍angular原理之前,我们有必要先了解下mvvm模式在angular中运用.虽然在angular社区一直将angular统称为前端MVC框架,同时angular团队也称它为MVW(What ...

  5. Silverlight中使用MVVM(1)--基础

    Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 Silverlight中使用MVVM(4)—演练 ...

  6. Silverlight中使用MVVM(3)

    Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 Silverlight中使用MVVM(4)—演练 ...

  7. Silverlight中使用MVVM(1)

    Silverlight中使用MVVM(1)   Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 ...

  8. MVVM模式下弹出窗体

    原地址:http://www.cnblogs.com/yk250/p/5773425.html 在mvvm模式下弹出窗体,有使用接口模式传入参数new一个对象的,还有的是继承于一个window,然后在 ...

  9. js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别

    MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...

随机推荐

  1. sql中时间的一些特殊转换

    1.修改时间的秒和微秒 create table a (Dtime datetime);insert into aselect '2013-08-30 17:59:35' union allselec ...

  2. centos7 搭建 docker 环境

    1. 安装centos7  http://isoredirect.centos.org/centos/7/isos/x86_64/ 下载 everything 版本,最小化版本可能缺失很多东西 我是在 ...

  3. GA遗传算法解析

    LinJM  @HQU 谈及遗传算法,我首先想到的就是孟德尔的豌豆实验.当然,遗传算法实质上并不能用豌豆实验说明,豌豆实验探讨了分离定律和自由组合定律,而遗传算法所借鉴的并不是这两个定律.遗传算法,简 ...

  4. 统计中的PV,UV是的意思(转)

    PV(访问量):即Page View, 即页面浏览量或点击量,用户每次刷新即被计算一次. UV(独立访客):即Unique Visitor,访问您网站的一台电脑客户端为一个访客.00:00-24:00 ...

  5. JS家的排序算法

    由于浏览器的原生支持(无需安装任何插件),用JS来学习数据结构和算法也许比c更加便捷些.因为只需一个浏览器就能啪啪啪的调试了.比如下图我学习归并排序算法时,只看代码感觉怎么都理解不了,但是结合chro ...

  6. Servlet中文乱码解决方法

    程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件. 字节流和字符流的区别: 在Java.io包中操作文件内容的主要有两大类:字节流.字符流,两类都分为输入和输出操作. 在字节流中输 ...

  7. DevExpress的GridView设置特定行的样式

    GridView控件绑定事件: gridView_SampleData.CustomDrawCell += gridView_SampleData_CustomDrawCell; 根据自定义逻辑来改变 ...

  8. Linux下搭建Oracle11g RAC(5)----配置ASM磁盘

    将共享磁盘格式化.然后用asmlib将其配置为ASM磁盘,用于将来存放OCR.Voting Disk和数据库用. 注意:只需在其中1个节点上格式化就可以,接下来我们选择在node1节点上格式化. 这里 ...

  9. windows 8 解决端口(COM和LPT)问题:Prolific USB-to-Serial Comm Port(COM4)驱动异常的问题

    本来都正常的,一段时间后就不能用了,网上搜索了一圈,现记录下来,供大家参考 操作系统是win8 64位的 参考网址(http://blog.sina.com.cn/s/blog_92942dba010 ...

  10. C#开发的进化史

    1.数据类型的进化 C#1中实现Product类型代码 public class Product { string name; public string Name { get { return na ...