在项目中,凡是涉及到表格的地方用的最多的控件,自然少不了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选择控件封装的更多相关文章
-
Atitit.ui控件---下拉菜单选择控件的实现select html
Atitit.ui控件---下拉菜单选择控件的实现select html 1. 调用& model的实现 1 2. -----select.jsp------ 1 1. 调用& m ...
-
WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题
问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...
-
关于使用MVVM模式在WPF的DataGrid控件中实现ComboBox编辑列
最近在做一个组态软件的项目,有一个需求需要在建立IO设备变量的时候选择变量的类型等. 建立IO变量的界面是一个DataGrid实现的,可以一行一行的新建变量,如下如所示: 这里需要使用带有ComboB ...
-
angular中的MVVM模式
在开始介绍angular原理之前,我们有必要先了解下mvvm模式在angular中运用.虽然在angular社区一直将angular统称为前端MVC框架,同时angular团队也称它为MVW(What ...
-
Silverlight中使用MVVM(1)--基础
Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 Silverlight中使用MVVM(4)—演练 ...
-
Silverlight中使用MVVM(3)
Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 Silverlight中使用MVVM(4)—演练 ...
-
Silverlight中使用MVVM(1)
Silverlight中使用MVVM(1) Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 ...
-
MVVM模式下弹出窗体
原地址:http://www.cnblogs.com/yk250/p/5773425.html 在mvvm模式下弹出窗体,有使用接口模式传入参数new一个对象的,还有的是继承于一个window,然后在 ...
-
js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别
MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...
随机推荐
-
dictionaryWithContentsOfFile:方法
dictionaryWithContentsOfFile:方法的功能是创建一个字典,将字典中的内容设置为指定文件中的所有内容, 语法:(id)dictionaryWithContentsOffilE. ...
-
Linux开机后 systemd 自动启动 ceph osd mon进程
机房操作失误导致机架或主机掉电是偶尔发生的事情,那么怎么在这种情况下,让Ceph服务随OS启动而快速启动呢 ? 如下是一个简单方法: 在OSD主机上执行如下命令: sudo ln -s /usr/li ...
-
无法卸载windows组件?提示zClientm.exe
在卸载windows的组件: wmp, outlook, msessager等,提示: 找不到zClientm.exe 文件? 原来, zclientm.exe是windows的游戏组件依赖的文件, ...
-
【积硅计划】http协议基础
http:超文本传输协议,它允许将超文本标记(html)文档从web服务器传送到浏览器.目前版本HTTP/1.1 http请求过程: proxy:代理服务器,网络信息的中转站.功能如下: ...
-
[Effective C++ --017]以独立语句将newed对象置入智能指针
这一节也比较简单,先假设我们有如下的函数: int foo(); void memFoo(shared_ptr<T> pw, int foo); 现在假设我们要调用memFoo函数: me ...
-
.net(C#)访问Oracle数据库的几种免安装组件的对比(转)
原文地址 [内容为转载,个人推荐还是用官方的组件,推荐使用 Oracle.DataAccess.dll ] .net(C#)编程过程中,使用到了以下三种免安装的Oracle访问组件,能够不安装Orac ...
-
24种设计模式--门面模式【Facade Pattern】
大家都写过纸质的信件吧,比如给女朋友写情书什么的,写信的过程大家都还记得吧,先写信的内容,然后写信封,把信放到信封中,封好,投递到信箱中进行邮递,这个过程还是比较简单的,虽然简单,这四个步骤都是要跑的 ...
-
hdu2209翻纸牌游戏
翻纸牌游戏 Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
-
BloomFilter(布隆过滤器)
原文链接:http://blog.csdn.net/qq_38646470/article/details/79431659 1.概念: 如果想判断一个元素是不是在一个集合里,一般想到的是将所有元素保 ...
-
go语言学习--处理map的无序输出
最近工作中遇到了这样的一个场景,需要处理一个无限极分类的问题,对于数据结构的定义首先想到了,map,map[int]map[int]struct.通过两层map的定义归类parent_id和id的关系 ...