UWP开发之Mvvmlight实践三:简单MVVM实例开发(图文详解付代码)
在做MVVM各种框架对比之前,我觉得有必要先自己做一个简单的MVVM实现案例比较好,这样就可以看到自己实现的时候有那些不方便的地方。而各种框架又是怎么解决我们这些麻烦的。
案例介绍:用户登录画面,没有输入用户ID数据时按钮不可用,输入用户ID数据后按钮可以使用。点击按钮获取用户名信息。
案例下载:https://github.com/NewBLife/UWP/tree/master/MvvmDemo
1、创建UWP空项目
将False改成True,这应该都懂的
2、构建项目结构
按照MVVM模式思想,一般都会包含Views,ViewModels,Models,如果项目比较复杂在ViewModel和Model之间还会有Service层。
复杂系统情况:
3、创建Binding基类
MVVM核心技能之一:绑定。如果是单向显示数据的话直接使用类属性就可以,如果想交互双向绑定的实现INotifyPropertyChanged接口。其中的PropertyChanged事件会通知UI改变绑定值状态。
代码如下:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices; namespace MvvmDemo.Common
{
/// <summary>
/// Viewmodel基类,属性双向绑定基础
/// </summary>
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; /// <summary>
/// 属性变更通知
/// </summary>
/// <param name="propertyName">属性名</param>
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
4、创建Command基类
MVVM核心技能二:ICommand。这个的存在使我们的UI逻辑可以搬迁到其他地方处理,给自动化单体测试与分工设计带来了可能。按钮的Click事件,Combox选择,列表选择等等都可以使用Command形式绑定到ViewModel的Command属性做处理。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; namespace MvvmDemo.Common
{
public class DelegateCommand<T>: ICommand
{
/// <summary>
/// 命令
/// </summary>
private Action<T> _Command;
/// <summary>
/// 命令可否执行判断
/// </summary>
private Func<T, bool> _CanExecute;
/// <summary>
/// 可执行判断结束后通知命令执行
/// </summary>
public event EventHandler CanExecuteChanged; /// <summary>
/// 构造函数
/// </summary>
/// <param name="command">命令</param>
public DelegateCommand(Action<T> command):this(command,null)
{
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="command">命令</param>
/// <param name="canexecute">命令可执行判断</param>
public DelegateCommand(Action<T> command,Func<T,bool> canexecute)
{
if(command==null)
{
throw new ArgumentException("command");
}
_Command = command;
_CanExecute = canexecute;
} /// <summary>
/// 命令执行判断
/// </summary>
/// <param name="parameter">判断数据</param>
/// <returns>判定结果(True:可执行,False:不可执行)</returns>
public bool CanExecute(object parameter)
{
return _CanExecute == null ? true : _CanExecute((T)parameter);
} /// <summary>
/// 执行命令
/// </summary>
/// <param name="parameter">参数</param>
public void Execute(object parameter)
{
_Command((T)parameter);
}
}
}
5、创建ViewModel
脱离UI的数据处理中心。让我们可以单独编写它的测试程序来完成UI测试。主要目的就是将DB数据整合为用户想看的数据。
代码如下:
using MvvmDemo.Common;
using MvvmDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace MvvmDemo.ViewModels
{
public class MainViewModel : ViewModelBase
{
private string _userId;
private string _userName;
private DelegateCommand<string> _loginCommand; /// <summary>
/// 用户名
/// </summary>
public string UserId
{
get
{
return _userId;
} set
{
_userId = value;
NotifyPropertyChanged();
}
}
/// <summary>
/// 用户名
/// </summary>
public string UserName
{
get
{
return _userName;
} set
{
_userName = value;
NotifyPropertyChanged();
}
}
/// <summary>
/// 登陆命令
/// </summary>
public DelegateCommand<string> LoginCommand
{
get
{
return _loginCommand
??(_loginCommand=new DelegateCommand<string>(
s=>
{
UserName = new UserModel().GetUserName(s);
},
s=>!string.IsNullOrEmpty(s)
));
}
}
}
}
6、创建View设置绑定
绑定6.0后有X:Bind,之前有Binding。x:Bind是编译时确定绑定对象,Binding是实行时确定绑定对象。总得来说X:Bind的速度比Binding快,在程序运行前就能发现绑定错误的问题。
这里直接就拿MainView做例子,更改下布局
<Page
x:Class="MvvmDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MvvmDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height=""/>
<RowDefinition Height=""/>
<RowDefinition Height=""/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> <TextBlock Text="用户ID:" Grid.Row="" Grid.Column="" Width="" />
<TextBlock Text="用户名:" Grid.Row="" Grid.Column="" Width="" />
<TextBox x:Name="txtUserID" Grid.Row="" Grid.Column="" Width="" Text="{x:Bind VM.UserId,Mode=OneWay}" />
<TextBlock x:Name="txbUserName" Grid.Row="" Grid.Column="" Width="" Text="{x:Bind VM.UserName,Mode=OneWay}" />
<Button x:Name="btnLogin" Content="Login" Grid.Row="" Grid.ColumnSpan="" Width="" HorizontalAlignment="Center"
Command="{x:Bind VM.LoginCommand,Mode=OneWay}"
CommandParameter="{Binding Text,ElementName=txtUserID,Mode=OneWay}"/>
</Grid>
</Page>
后台添加代码
/// <summary>
/// 可用于自身或导航至 Frame 内部的空白页。
/// </summary>
public sealed partial class MainPage : Page
{
public MainViewModel VM =>new MainViewModel(); public MainPage()
{
this.InitializeComponent();
this.DataContext = VM;
}
}
7、创建Model
由于这里没有复杂逻辑,就不添加Service了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace MvvmDemo.Models
{
public class UserModel
{
public string GetUserName(string userid)
{
return string.Format("取得成功:{0}",userid);
}
}
}
8、实行结果
输入内容前按钮自动不可用:
输入内容后按钮自动可用:
点击Login按钮:
9、总结
这种就是简单的登陆实现,涉及到了MVVM的View,Viewmodel,Model,以及XBind的用法。6.0后有X:Bind,之前有Binding。x:Bind是编译时确定绑定对象,Binding是实行时确定绑定对象。总得来说X:Bind的速度比Binding快,在程序运行前就能发现绑定错误的问题。登陆页面的按钮是随着输入自动判断是否可用,这个就是Icommand一个方法Canexcute的作用。可见自己实现Mvvm模式也不是很难的事情,不过随着项目的复杂加深就会有很多问题,比如Viewmode之间通信等,这个时候才是MVVM框架的优势所在。
UWP开发之Mvvmlight实践三:简单MVVM实例开发(图文详解付代码)的更多相关文章
- UWP开发之Mvvmlight实践七:如何查找设备(Mobile模拟器、实体手机、PC)中应用的Log等文件
在开发中或者后期测试乃至最后交付使用的时候,如果应用出问题了我们一般的做法就是查看Log文件.上章也提到了查看Log文件,这章重点讲解下如何查看Log文件?如何找到我们需要的Packages安装包目录 ...
- UWP开发之Mvvmlight实践一:如何在项目中添加使用Mvvmlight(图文详解)
最近一直在做UWP开发,为了节省成本等等接触到MVVMlight,觉得有必要发点时间研究它的用法与实现原理才行.如果有问题的地方或者有好的建议欢迎提出来. 随着移动开发的热门,Mvvmlight在An ...
- UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享
在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
- UWP开发之Mvvmlight实践二:Mvvmlight的核心框架MVVM与MVC、MVP的区别(图文详解)
最近UWP开发在海外很潮流,随着微软收购Xamarin,我们这些C#程序员也可以靠这杆小米枪挑战Android,IOS平台了. 那我们为什么选择MVVM做UWP开发?MVC,MVP,MVVM他们之间到 ...
- UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理
最近比较忙有一段时间没有更新了,再接再厉继续分享. 案例下载:https://github.com/NewBLife/UWP/tree/master/SuspendSample 先我们看看App在生命 ...
- UWP开发之Mvvmlight实践八:为什么事件注销处理要写在OnNavigatingFrom中
前一段开发UWP应用的时候因为系统返回按钮事件(SystemNavigationManager.GetForCurrentView().BackRequested)浪费了不少时间.现象就是在手机版的详 ...
- UWP开发之Mvvmlight实践四:{x:bind}和{Binding}区别详解
{x:bind}是随着UWP被推出而被添加的,可以说是Win10 UWP开发专有扩展.虽然 {x:Bind} 缺少{Binding} 中的一些功能,但它运行时所花费的时间和使用的内存量均比 {Bind ...
- UWP开发之Mvvmlight实践六:MissingMetadataException解决办法(.Net Native下Default.rd.xml配置问题)
最近完成一款UWP应用,在手机端测试发布版(Release)的时候应用莫名奇妙的强行关闭,而同样的应用包在PC端一点问题都没有,而且Debug版在两个平台都没有问题,唯独手机的Release版有问题. ...
- UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)
前面[UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理]章节已经提到过Template10,为了认识MvvmLight的区别特做了此实例. 原代码地址:ht ...
随机推荐
- web-inf目录和meta-inf目录
/WEB-INF/web.xml Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则. /WEB-INF/classes/ 包含了站点所有用的 class 文件,包括 se ...
- SEO网站内链匹配工具
最近在弄一个网站,想体验一下SEO方面的工作. 虽然自己是从事.NET方面工作的,但时间有限,所以用了DEDECMS作为网站的程序. 而SEO里面最重要的一项就是内链.但DEDECMS没有直接的内链匹 ...
- [LintCode] Best Time to Buy and Sell Stock II 买股票的最佳时间之二
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- siteserver cms选择栏目搜索无效
标签必须以空格分开,且option 的value必须给id不能给名称
- 分析错误:socket accept failed too many open files
步骤:1.--查看当前各个进程打开的文件句柄数,其结果的第一列表示句柄数,第二列表示进程号lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more 2. ...
- 下载apk文件浏览器会直接打开并显示乱码的问题
今天同事反映他的apk文件在自己的老项目中下载有问题:下载apk文件浏览器会直接打开并显示乱码,在别的项目中就没有问题. 后分析response的content-type发现,老项目的类型是text/ ...
- 使用--gc-section编译选项减小程序体积
本周在给程序添加功能的时候,突然发现,我只是写了几个函数,还没调用,size就变大了.这肯定是不行的嘛,没用的函数就应该不链接进来,占用我宝贵的空间. 这种功能,讲道理编译器肯定要支持的,于是搜了一下 ...
- LA
grmon -altjtag -u 公式rand()%(b-a),是求范围随机数的计算公式,%是做求余运算,正整数对n求余的范围肯定是在0~n-1之间,也就是rand()%(b-a)的范围是0~b-a ...
- SQL Server差异备份的备份/还原原理
SQL Server差异备份的备份/还原原理 记住一点:差异备份是基于最后一次完整备份的差异,而不是基于最后一次差异的差异 备份过程: 1-完整备份之后有无对数据库做过修改,如果有,记录数据库的最 ...
- ubuntu-14.04.2-desktop使用方法
一.安装VMware Tools 1. 在VMware Workstation11.1.0下安装Ubuntu镜像:ubuntukylin-14.04.2-desktop-amd64.iso 2. 点击 ...