zoukankan      html  css  js  c++  java
  • 从一个登录页面浅淡MVVM(三)

    在 ViewModels 中增加一个 ViewModelCommand ,通过 Action<Object> 执行实际的方法。

    ViewModelCommand.cs
    /// <summary>
    /// 使用 Action<Object> 作为通用的 Command,如果要使用 Action<T> 的其他形式,则要创建新的类型。
    /// 使用 struct 从 Heap 中进行存储,性能更高
    /// </summary>
    public struct ViewModelCommand : ICommand
    {
    private Action<Object> action;
    public Action<Object> ViewModelAction
    {
    get { return action; }
    set { action = value; }
    }

    public ViewModelCommand(Action<Object> act)
    {
    action
    = act;
    }

    public bool CanExecute(Object parameter)
    {
    return true;
    }
    public void Execute(Object parameter)
    {
    this.ViewModelAction(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
    add { }
    remove { }
    }
    }

    PS:日前,在看有关 Object Value  的用法时,提到了 struct ,struct 是存储在 Heap 上,而引用类型是存储在

    Stack 上的,在内存分配及垃圾回收等方面 struct 的性能更高,所以这里把 ViewModelCommand 改为 struct。

    在 LoginViewModel.cs 中增加两个Command,分别用于前台 UI 的两个 Button 的 Command 绑定。

    LoginViewModel.cs
    public ViewModelCommand GenerateValidationCodeCommand { get; private set; }
    public ViewModelCommand LoginCommand { get; private set; }

    public LoginViewModel()
    {
    this.Data = new User();
    this.GenerateValidationCodeCommand = new ViewModelCommand((Object parameter) =>
    {
    this.GenerateValidationCodeAsync();
    });
    this.LoginCommand = new ViewModelCommand((Object parameter) =>
    {
    if (this.Validate())
    {
    this.LoginAsync();
    }
    });
    }

    同时,尝试将要执行 Validation 的 UI 引用移入 ViewModel 中

    LoginViewModel.cs
    /// <summary>
    /// 用于控制UI的ValidationSummary
    /// </summary>
    public ValidationSummary ValidationSummary { get; set; }
    /// <summary>
    /// 用于控制UI的控件的校验
    /// </summary>
    public UIElementCollection ValidationUICollection { get; set; }

    /// <summary>
    /// 针对 ValidationSummary 和 ValidationUICollection 进行校验
    /// </summary>
    /// <returns></returns>
    public bool Validate()
    {
    if (this.ValidationSummary != null && this.ValidationSummary.HasErrors)
    {
    return false;
    }
    else if (this.ValidationUICollection != null)
    {
    // 扩展方法,校验各个控件的数据绑定
    this.ValidationUICollection.ValidateSource();
    if (this.ValidationSummary != null && this.ValidationSummary.HasErrors)
    {
    return false;
    }
    }
    return true;
    }

    这样,View 就更简单了,在 Xaml 中变为

    <Button Content="换一个" Grid.Column="3" Grid.Row="2" Height="23" Margin="8"
    Name
    ="btnChangeValidationCode" Width="75"
    Command
    ="{Binding GenerateValidationCodeCommand}" />

    <Button Content="登录" Grid.Row="3" Grid.ColumnSpan="4" Margin="8" Name="btnLogin"
    Command
    ="{Binding LoginCommand}" />

    LoginPage.cs 变为

    LoginPage.cs
    public partial class LoginPage : Page
    {
    LoginViewModel loginVM;

    public LoginPage()
    {
    InitializeComponent();
    this.loginVM = new LoginViewModel()
    {
    ValidationSummary
    = this.validationSummary1,
    ValidationUICollection
    = this.LayoutRoot.Children
    };
    this.loginVM.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(loginVM_PropertyChanged);
    this.Loaded+=new RoutedEventHandler(LoginPage_Loaded);
    }

    void loginVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
    if (e.PropertyName == "IsDone")
    {
    if (this.loginVM.IsDone)
    {
    // 登录成功,执行跳转
    }
    }
    else if (e.PropertyName == "Message")
    {
    // 可以在 UI 上将 Message 也和 TextBlock 等进行绑定,以显示消息
    MessageBox.Show(this.loginVM.Message);
    }
    }

    void LoginPage_Loaded(object sender, RoutedEventArgs e)
    {
    this.loginVM.GenerateValidationCodeAsync();
    this.DataContext = this.loginVM;
    }

    }

    使用 MVVM ,好处很明显,LoginPage.cs 中的代码几乎减少至只剩下 实例化 ViewModel 和为 DataContext

    赋值的语句了,代码人员和设计人员可以分开工作。

     

    但是,View 和 ViewModel 之间如何依赖?

    显然 View 是依赖于 ViewModel 的,但是 ViewModel 该不该依赖于 View ,也就是说 LoginPageViewModel 该不该

    拥有一个指向 LoginPage 实例的属性或字段?

     

    在 Silverlight Templated Control 中,代码和Xaml是分离的,代码和Xaml通过约定的 TemplatePart 的名字各自

    进行编码,而代码在运行时通过 GetTemplateChild(name) 取得控件的实例,

    这种分离,允许我们把 Silverlight Templated Control定义在最低层次的类库,而在运行时于最高层的 App 应用程序中

    重新为 Silverlight Templated Control 指定外观,那么,在 MVVM 中,View 和 ViewModel 是否也能这样分离呢?

     

    如果要实现这种分离,那么 ViewModel 便不可能依赖于 View ,最多只能是定义一些 interface,View 从 interface 中

    派生,而 ViewModel 依赖于 interface。

    联想起 ASP.NET MVC 2,每一个页面对应一个 Model,这个 Model 其实就相当于是 ViewModel,依稀记得 MVC 2 中

    ViewModel 是不会关注 View 的。

     

    嗯,存疑,先至此,欢迎各位进行指正和讨论。

  • 相关阅读:
    React Native Android打包apk
    React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现
    使用react native制作的微博客户端
    Shell 脚本中 '$' 符号的多种用法
    Shell编程 | 脚本参数与交互及常见问题
    Shell编程-条件测试 | 基础篇
    Shell编程-控制结构 | 基础篇
    Python运维中20个常用的库和模块
    20款开发运维必备的顶级工具
    Linux 系统结构详解
  • 原文地址:https://www.cnblogs.com/Sunpire/p/1916943.html
Copyright © 2011-2022 走看看