• 包氏波动思想


          有了前面介绍的AttachedBehavior,所有控件的任意方法都可以转换为Command了。

          但是,对于列表控件而言,还有一条解决方案,这包括DataGrid、ListBox、ComboBox等等,而对于CheckBox、RadioButton而言,也可以将其视为由多个选项组成的控件,所以,也在本文涉及的范围之内。

          先来看一个例子:

          (一)DataGrid

          一个DataGrid,选择其中的任意一行,都会在GroupBox中显示这一行的详细信息。对,这是Master-Detail技术:

          在传统窗体编程模型中,使用DataGrid的SelectionChanged事件,可以轻松实现这一功能:       

    <data:DataGrid SelectionChanged="dataGrid1_SelectionChanged" … >
            private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                var selectStudent 
    = e.AddedItems[0as Student;
                tbUserName.Text 
    = selectStudent.UserName;
                tbScore.Text 
    = selectStudent.Score.ToString();
            }

          clip_image002

          代码下载:WpfApplication7_1.zip

          但如今,我们要使用MVP来实现这个小例子,所以像SelectionChanged这样的事件是不能使用的,怎么办呢?

          仔细观察GridView控件,会发现它有一个SelectedItem属性,当SelectionChanged事件触发后,这个属性会被设置为当前选中的那一行。于是,我们在数据(Model)中,可以建立同名的一个属性,将它们进行绑定。那么,选中不同的行,GridView的SelectedItem就会改变,这一“波动”会导致数据(Model)中的相应属性(这里是SelectedStudent)也跟着变动,我们可以在数据(Model)中捕获到这一“波动”,从而执行一些自己的逻辑。 

        <data:DataGrid ItemsSource="{Binding StudentList}" SelectedItem="{Binding SelectedStudent}" … />


        public class ScoreListViewModel : INotifyPropertyChanged
        
    {
            
    public ScoreListViewModel()
            
    {
                
    this.StudentList = StudentService.RetrieveStudentList();
                
    this.SelectedStudent = this.StudentList[0];
            }


            
    public ScoreListView View getset; }

            
    private Student selectedStudent;

            
    public Student SelectedStudent
            
    {
                
    get
                
    {
                    
    return this.selectedStudent;
                }

                
    set
                
    {
                    
    if (this.selectedStudent != value)
                    
    {
                        
    this.selectedStudent = value;
                        OnPropertyChanged(
    "SelectedStudent");
                    }

                }

            }

        }

          代码下载:WpfApplication7_2.zip

          这种设计思想是我在实际编程中自己琢磨出来的,事后在Prism的codeplex论坛上发现之前就已经有人这么实现了。真是英雄所见略同啊!因为这种设计的适用性是很广的,所以我将其总结为——

          包氏波动思想定义:对于列表性控件(DataGrid、ListBox、ComboBox等等),以及像CheckBox、RadioButton这样的带有选项集合的控件,它们都具有类似SelectedItem这样的属性,我们可以在MVP模式中绑定这些属性,以监视选择项的变化。

          接下来的章节我将分别展示这些控件的另类绑定方式,以证实包氏波动思想的伟大价值。


          (二)ListBox

          将上面例子中的DataGrid换为ListBox就可以了,其它地方无需任何改变。 

        <ListBox Margin="12,12,66,144" Name="listBox1" ItemsSource="{Binding StudentList}" SelectedItem="{Binding SelectedStudent}">
            
    <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妥协的产物,尤其在描述数据上,是远远不如包氏波动思想的。

          哈哈,老包卖瓜,自卖自夸,不管这种思想是不是姓包,我们都要养成“基于数据编程”的习惯,而不再是“基于控件编程”。


          这是一种境界的提升。

  • 相关阅读:
    20160205.CCPP体系详解(0015天)
    盘点各专业到古代都能干些啥
    一份简单的在 Linux下编译及调试 C 代码的指南
    WordPress Gravatar国内加载缓慢解决办法
    linux修改mysql字符集编码
    阿里合伙人邵晓锋:什么是创业者应该抵制的诱惑?
    6月27日云栖精选夜读:细数智能家居的痛点
    6月26日云栖精选夜读:成为一名Java高级工程师你需要学什么
    搭建百万级别邮件发送平台
    黑科技实验室:这些高级装备厉害了!
  • 原文地址:https://www.cnblogs.com/Jax/p/1582889.html
Copyright © 2020-2023  润新知