包氏波动思想
有了前面介绍的AttachedBehavior,所有控件的任意方法都可以转换为Command了。
但是,对于列表控件而言,还有一条解决方案,这包括DataGrid、ListBox、ComboBox等等,而对于CheckBox、RadioButton而言,也可以将其视为由多个选项组成的控件,所以,也在本文涉及的范围之内。
先来看一个例子:
(一)DataGrid
一个DataGrid,选择其中的任意一行,都会在GroupBox中显示这一行的详细信息。对,这是Master-Detail技术:
在传统窗体编程模型中,使用DataGrid的SelectionChanged事件,可以轻松实现这一功能:
{
var selectStudent = e.AddedItems[0] as Student;
tbUserName.Text = selectStudent.UserName;
tbScore.Text = selectStudent.Score.ToString();
}
但如今,我们要使用MVP来实现这个小例子,所以像SelectionChanged这样的事件是不能使用的,怎么办呢?
仔细观察GridView控件,会发现它有一个SelectedItem属性,当SelectionChanged事件触发后,这个属性会被设置为当前选中的那一行。于是,我们在数据(Model)中,可以建立同名的一个属性,将它们进行绑定。那么,选中不同的行,GridView的SelectedItem就会改变,这一“波动”会导致数据(Model)中的相应属性(这里是SelectedStudent)也跟着变动,我们可以在数据(Model)中捕获到这一“波动”,从而执行一些自己的逻辑。




























这种设计思想是我在实际编程中自己琢磨出来的,事后在Prism的codeplex论坛上发现之前就已经有人这么实现了。真是英雄所见略同啊!因为这种设计的适用性是很广的,所以我将其总结为——
包氏波动思想定义:对于列表性控件(DataGrid、ListBox、ComboBox等等),以及像CheckBox、RadioButton这样的带有选项集合的控件,它们都具有类似SelectedItem这样的属性,我们可以在MVP模式中绑定这些属性,以监视选择项的变化。
接下来的章节我将分别展示这些控件的另类绑定方式,以证实包氏波动思想的伟大价值。
(二)ListBox
将上面例子中的DataGrid换为ListBox就可以了,其它地方无需任何改变。
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=UserName}" Width="40" />
<TextBlock Text="{Binding Path=Score}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
代码下载: WpfApplication7_3.zip
(三)CheckBox
CheckBox中有一个属性IsChecked,我们只要监视着该属性的波动,就可以了。
代码下载: WpfApplication7_4.zip
(四)RadioButton
这个实现起来比较费事,细节请参见Clingingboy的文章:《WPF and SL RadioButtonList Tip》。
这个土人居然没给出个Demo,我只好自己动手丰衣足食,代码下载: WpfTestRadioButton.zip
但是我们发现,这个例子太简单了,只是2个性别“男”和“女”的选择,如果用CheckBox也是可以模拟出来的。
于是,在此基础上,我试着添加了第3性“女博士”,来扩展RadionButton的应用。
代码下载: WpfTestRadioButton_extension.zip
(五)ComboBox
这个控件的波动思想,在WPF中实现起来比较简单。
代码下载: WpfTestComboBox.zip
注:这个控件玩起来有时候比较烦,就是当下拉列表中有一行默认空白选项时,我们会在《最复杂的MVVM模式》一文中遇到这一场景。
(六)总结
最常用的就是这几种了,也是最典型的几种。其它列表控件的绑定方式均可依样画葫芦,我这里就不多讲了。
对于列表控件,究竟是使用AttachedBehavior,还是使用“包氏波动思想”(继续陶醉中),我的取舍是后者,只有在不能用波动思想的时候,才会考虑AttachedBehavior。波动思想俨然是基于数据的,这和MVP模式将数据从UI中剥离不谋而合;而AttachedBehavior则是传统Event编程模型的变形,我一直认为它是Event和Command妥协的产物,尤其在描述数据上,是远远不如包氏波动思想的。
哈哈,老包卖瓜,自卖自夸,不管这种思想是不是姓包,我们都要养成“基于数据编程”的习惯,而不再是“基于控件编程”。
这是一种境界的提升。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架