zoukankan      html  css  js  c++  java
  • MVVM在Silverlight中应用

    本篇会帮助从MVVM了解进入实际编码入门, 然后对实际运用细节提出我个人看法解决方式[当然有可能是不成熟 也欢迎提出你的见解]. 如果你认为对MVVM运用已经驾轻就熟 敬请飘过. 

    <1>为什么要用MVVM?

    关于这个问题 我们把它范围更缩小一点 单一放到Silverlight中来看.一方面Silverlight带来很多新的技术体验动画,3D 等  另外一方面我们在编程上UI层就更加细节化了.可定制.同时新特性Binding、Dependency Property、Routed Events、Command、DataTemplate的不断出现, 也为原来适用WPF的MVP模式发生转变, Silverlight需要一个适合自己的框架来"武装"自己, 新特性的出现加速MVVM基于MVP中演变成型的速度. 这就导致MVVM从MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架..

    <2>如何运用MVVM?

      既然MVVM出现时一个不断演变过程, 那么它的出现回给我们的原来Silverlight编码产生哪些变化?这个问题我稍后会解释.先让我们学会使用这个MVVM.

     <2.1>我们要做什么?

     为了达到完整演示使用MVVM整个过程,下面我会写一个小型的DEMO来阐述如何使用MVVM. 在进入编码前又必要了解一下我们这个程序要做什么  具体需求如下:

    现在有一个场景:

     在工业批量生产中, 会使用多台自动化机器, 而人的作用就是这些自动化机器的管理者. 管理者通过程控机[监控自动化机器运行状态一种机器] 实时动态采集多台自动化机器的运行状态参数. 来保证机器正常运行. 说明整个控制流程图:

    其实这个是一个简单单一流程. 反映到程序中 我们就要通过程控机Com通信端口采集多个自动化机器的运行参数并反映当前运行状况. ok 需求明确了. 那就让我们用MVVM在Silverlight模拟实现.

    <2.2>进入编码

    MVVM具体进行拆分就可以分为M-V-VM 三个层次,M[Model]—V[View]—VM[ViewModel],第一个M代表数据实体Model, View也是UI. 那么VM来做什么?当我们有了漂亮View和可操作的Model. 用户通过View来与程序进行交互.Silverlight提供了我们良好Binding特性, 我们可以把View中控件与Model的特定属性进行Binding操作, 页面数据就能直接反馈到Model上来, 貌似很好,但是实际运用中我们发现, View中可能出现类型有多个, 而我们的Model定义属性类型是唯一的,  同时页面数据需要过滤转换处理, 这就麻烦了, 我们只能修改Model, 可是针对多个页面难道我们修改多次吗? 那么也就违反OO编程第一原则ISP类单一职责. 不可取.同时这时的Model也变得臃肿庞大, 后期代码维护代价足以能够折磨你到"抓狂".

    这个时候我们才想起有点冷落的VM了, 我们可以把View除了显示以外所有活 都交给它来做. 它功能就充分体现了 隔离View与Model直接关联,同时要满足View所有向后台请求数据的需求. 备受冷落的VM终于有了用武之地了.清晰流程图:

    我们先通过利用程序检索一下当前机器运行状态,利用VS2010搭建一个Silverlight Application 结构如下:

    从结构能清晰看出整体数据流向: 用户操作View输入数据,利用Silverlight 4支持的ICommand通过ViewModes访问DataSource数据源, 并把相关数据更新给ViewModel的属性,View通过TwoWay双向绑定看到更新数据..

    定义View:

    有了View我们再来封装Model, 我们控制对象是机器Machine 封装成Model:

    1
    2
    3
    4
    5
    6
    public class ComMachine
        {
            public string Id { get; set; }
            public string MachineName { get; set; }
            public string State { get; set; }
        }

    紧跟着定义ViewModel:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    /// <summary>
       /// 测试单一MVVM框架数据流向
       /// Author:chenkai Date:2010年8月10日15:35:43
       /// </summary>
       public class MachineViewModel:INotifyPropertyChanged
       {
     
           #region INotifyPropertyChanged Members
     
           public event PropertyChangedEventHandler PropertyChanged;
     
           #endregion
     
           public MachineViewModel(List<Models.ComMachine> getcuslist)
           {
               this.customerlist = getcuslist;
               this.queryCommand = new Command.QueryDataCommand(this);
           }
     
           //查询数据
           private List<Models.ComMachine> customerlist = null;
     
           //搜索关键字
           private string searchKey = string.Empty;
     
           public string SearchKey
           {
               get { return searchKey; }
               set 
               
                   searchKey = value;
                   if (PropertyChanged != null)
                       this.PropertyChanged(this, new PropertyChangedEventArgs("SearchKey"));
               }
           }
     
           //搜索结果
           private string searchResult = string.Empty;
     
           public string SearchResult
           {
               get { return searchResult; }
               set 
               {
                   searchResult = value;
                   if (PropertyChanged != null)
                       this.PropertyChanged(this, new PropertyChangedEventArgs("SearchResult"));
               }
           }
     
           //搜索Command
           private ICommand queryCommand = null;
     
           public ICommand QueryCommand
           {
               get { return queryCommand; }
           }
     
           //查询数据
           public void QueryDate()
           {
               if (!string.IsNullOrEmpty(this.searchKey))
               {
                   Models.ComMachine QueryCustomer = null;
                   foreach (Models.ComMachine getcustomer in DataSource.GetCustomerList())
                   {
                       if (getcustomer.Id.Equals(this.searchKey))
                       {
                           QueryCustomer = getcustomer;
                           break;
                       }
                   }
     
                   if (QueryCustomer != null)
                   {
                       this.SearchResult = "机器名称:" + QueryCustomer.MachineName + Environment.NewLine + "可用状态:" + QueryCustomer.State;
                   }
                   else
                   {
                       MessageBox.Show("机器编号不存在!");
                       this.SearchKey = string.Empty;
                         
                   }
               }
               else
               {
                   MessageBox.Show("请输入你要查询的机器编号ID!");
               }
           }

    ViewModel完全为View页面做的量身定制的类,实现 INotifyPropertyChanged接口当对Viewmodel属性值发生变更时便进行通知. 另外一个很重要地方是就是当View调用Command命令时,需要在ViewModel中进行关联.

    通过上面我们能看出View中实现的对ViewMode属性Bingding和对查询操作Command调用.  也就是说调用Binding和Command是可以写在XAML中的,而真正定义Binding和Command实现描述的代码却在ViewModel中.

    Command定义:

     在Silverlight 3版本是XAML页面并不支持直接绑定Command. 在 Silverlight 4 中,ButtonBase 和 Hyperlink 支持 CommandCommandParameter 属性。Command 属性可以通过 {Binding} 用法引用来自视图模型数据源的 ICommand 实现。 然后由 Silverlight 输入系统在运行时解释该命令。关于更多信息,请参见 ButtonBase.CommandHyperlink.Command. 而在WPF中提供常用应用程序所用的命令集,常用的命令集包括:ApplicationCommands, ComponentCommands, NavigationCommands等,SL 4也正在WPF用户强烈呼声在加入对Comnand绑定支持.

    SL 3中我们在定义并实现ICommand接口后, 调用往往放在类似事件中需要手动处理.这样有什么不好地方?

    在没有结合command patter前,用silverlight进行异步调用的确显得很简单,可问题在于如果应用程序再多一些即有多个异步调用的话,我们将就需要添加一些按钮,而问题也就在于我们不能确定哪个调用属于哪个按钮,即行为与UI不能产生直接有效的映射关系,而Silverlight 4Command的全面支持也是完全解除这个调用障碍.

    我在技术群中有人曾这样直接问过我一个Command问题:

    当一个Button按钮有一个Click事件 同时还绑定一个后台调用的Command  当点击按钮时问他们执行顺序? 这个问题当时确实难住了我 平时这样细节没有注意.

    经过测试发现调用顺序是: 先调用Click事件 然后才通过程序对Command解析才调用Command 的Excute方法.

    还有一个关于Command调用场景问题:

    页面有一个Button, 当该Button被点击的时候我们要完成一些操作,  将该操作封装成一个Command并绑定到该Button上就可以了, 但如果我们要在Button被Load的时候执行另外一些操作呢? 

    问题就出现了,由于Button没有直接被Load事件所触发的Command, 所以使用Command就无效了.正如一个控件没有某个属性并且在不继承的情况下而采用AttachProperty一样, 我们可以采用AttachBehavior.写的很乱啊.

    http://www.cnblogs.com/chenkai/category/178378.html

  • 相关阅读:
    Python之路【第二十九篇】:面向对象基础
    Python之路【第二十八篇】:生成器与迭代器
    爬虫实战---爬取猫眼电影
    Selenium库详解
    PyQuery库详解
    BeautifulSoup解析库详解
    深浅拷贝的使用场景分析
    关于大数据量下Core Data的数据迁移
    IOS5中的新增方法详解
    自定义UISearchBar
  • 原文地址:https://www.cnblogs.com/flyinghigher/p/2557725.html
Copyright © 2011-2022 走看看