在上一章中,我们只是开了个头而已,然而在这一章中,我们将看到一点实际的代码了。我构想了很久,怎样让新手能快速掌握我想要传达的知识,然后我得出一个结论:一定一定要简单化,并且要有看的见摸的着的代码实例。好吧,我们开始。打开你的VS2010,新建一个WPF项目,命名为MvvmTutorial即可。紧接着,在当前Solution添加4个文件夹,分别为:Infrastructure, Views, ViewModels, Models。然后,把App.xaml改成如下:<
Application x:Class="MvvmTutorial.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
</Application >
把MainWindow.xaml,MainWindow.xaml.cs删掉。在Views下添加一个新的WPF Window,命名为ShellView。在App.xaml.cs中加入:protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var shell = new ShellView();
shell.Show();
}
都完成了吗?现在按F5,你应该可以看到你的程序正常运行,并且已经可以看到主窗体了。至此,我们只是做了一些准备工作。Shell其实就是壳的意思,每一个Windows程序都会有一个主窗体,也就是一个壳,我们在这个壳上面拼凑各种View来构成一个丰富的应用程序。现在我们来看一下具体我们要做些什么。我说过,尽量简单化,所以我们这章的任务很简单:就是把一些联系人显示在主窗体里。我们的联系人很简单,只有两个属性:名字和电话号码。我个人喜欢从ViewModel这一层出发,但是许多朋友还是习惯从Model层写起,那么我们就先来研究一下Model,即实体。在第一章中有人问是否应该在Model里实现INotifyPropertyChanged接口,我个人认为这个没有特别的死的做法。有点人愿意把Model尽量简单化,也就是说只是一个数据的载体而已,而把所有与View打交道的事情全部推给ViewModel。然而对于我们这个简单的例子,我选择让Model也实现INotifyPropertyChanged接口,如此一来,当我们对Model做出修改后,View上就可以显示出变化了(不过在今天这一章里,我们暂时不讨论ViewModel/Model的修改)。现在,在Models下添加一个Contact类。我们的Model,很简单,具体是这个样子的:using MvvmTutorial.Infrastructure;
namespace MvvmTutorial.Models
{
/// <summary >
/// Our Contact model, which stores data retrieved from data persistence layer
/// </summary >
public class Contact : ObservableObject
{
#region Fields
string _name;
string _phoneNumber;
#endregion // Fields
#region Properties
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
RaisePropertyChanged(() = > Name);
}
}
}
public string PhoneNumber
{
get
{
return _phoneNumber;
}
set
{
if (_phoneNumber != value)
{
_phoneNumber = value;
RaisePropertyChanged(() = > PhoneNumber);
}
}
}
#endregion // Properties
}
}
你们可能注意到了这个Contact实际上继承了ObservableObject。这是一个抽象的基类,由于我们将来会有很多类都要实现INotifyPropertyChanged接口,所以我在这里写了一个基类。在Infrastructure下添加一个ObservableObject:using System;
using System.ComponentModel;
using System.Linq.Expressions;
namespace MvvmTutorial.Infrastructure
{
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public virtual void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public void RaisePropertyChanged<T >(Expression<Func<T > > propertyExpression)
{
var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
this.RaisePropertyChanged(propertyName);
}
}
}
好的,这里我要说一下,其实这个类不是我个人写的,而是“剽窃”了一些现有的开源代码,拼凑起来的。请注意PropertySupport,这是一个静态类,它其实来自于微软的Prism框架里一小段代码,我之所以这样做只是让大家看的更清楚这些MVVM的框架内部大体是怎么回事,其实都是大同小异的。请在Infrastructure下添加PropertySupport:using System;
using System.Linq.Expressions;
using System.Reflection;
namespace MvvmTutorial.Infrastructure
{
public static class PropertySupport
{
public static string ExtractPropertyName<T >(Expression<Func<T > > propertyExpression)
{
if (propertyExpression == null)
{
throw new ArgumentNullException("propertyExpression");
}
var memberExpression = propertyExpression.Body as MemberExpression;
if (memberExpression == null)
{
throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
}
var property = memberExpression.Member as PropertyInfo;
if (property == null)
{
throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
}
var getMethod = property.GetGetMethod(true);
if (getMethod.IsStatic)
{
throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
}
return memberExpression.Member.Name;
}
}
}
有的人可能会问“PropertySupport”到底是干嘛的?其实我们经常写这样的代码:RaisePropertyChanged("SomeProperty"),这个代码本身没有任何问题,但是我们传入的是一个string,这也就暗示了两个小问题:1.当你的Property改名字以后,你需要修改这个string;2.输入string是个稍微容易出错的过程(打字错误)。那么PropertySupport.ExtractPropertyName便在牺牲了一点点效率的前提下,通过指定一个Expression来获得其属性的名字。所以我们就可以写成:RaisePropertyChanged(() = > PhoneNumber);如此一来,你只需要指定哪个属性即可,至于它的名字,不需要你操心,而且当下次你修改PhoneNumber为PrivatePhoneNumber后,你也不需要修改任何string。Okay,既然我们说了要显示出一系列联系人,我们便需要一个View和ViewModel。在ViewModels下添加ContactMasterViewModel:using System.Collections.Generic;
using System.Collections.ObjectModel;
using MvvmTutorial.Infrastructure;
using MvvmTutorial.Models;
namespace MvvmTutorial.ViewModels
{
public class ContactMasterViewModel : ObservableObject
{
#region Fields
private bool _isLoaded;
private ObservableCollection<Contact > _items = new ObservableCollection<Contact >();
#endregion // Fields
#region Properties
public IEnumerable<Contact > Items
{
get
{
// If we load this view model in design mode (for example, in VS or Expression),
// we add some random data so that we can preview the layout of our view
if (DesignHelper.IsInDesignMode)
{
for (int i = 0; i < 25; ++i)
{
_items.Add(new Contact().GenerateRandomData());
}
}
else if (!_isLoaded)
{
Load();
}
return _items;
}
}
#endregion // Properties
#region Private Methods
private void Load()
{
// TODO: Once we finish the implementation of data persistence layer,
// we need to re-write this code to make this method work for real-world app.
// We haven't implemented data persistence
// Therefore, we temporarily load some random data in memory
for (int i = 0; i < 25; ++i)
{
_items.Add(new Contact().GenerateRandomData());
}
_isLoaded = true;
}
#endregion // Private Methods
}
}
注意这里面的DesignHelper:在Infrastructure下添加DesignHelper类:
分享到:
相关推荐
一个 基于 MVVM LIGHT程序实例,内附详细的教程。包括1.1 MVVM Light Toolkit下载,安装 目录 1 MVVM Light的安装 1 1.1 MVVM Light Toolkit下载 1 1.2 MVVM Light Toolkit安装 2 2 程序实例 3 2.1 建立工程文件 3 ...
Vue\千锋java教程:068 Vue-了解前端知识体系.mp4章节10-前端知识-Vue\千锋java教程:069 Vue-了解前后分离的演变史.mp4章节10-前端知识-Vue\千锋java教程:070 Vue-了解前端 MVVM 模式.mp4章节10-前端知识-Vue\千锋...
MVVM Light Toolkit是一款轻量级的MVVM工具库,主要用于构建MVVM应用程序,包括Binding和Messenger两大部分,可以添加Data binding不支持...MVVM Light Toolkit安装教程 1、双击msi文件,进入欢迎界面,点击next 2
个人封装作为日后开发框架,当前仅集成了MVVM基础框架,未添加其他基础工具类软件架构基于MVVM框架的kotlin开发框架安装教程项目根目录build.gradle中添加allprojects {repositories {...maven { url '' }}}2....
MVVM + Kotlin + Retrofit2 +刀柄+协程+ LiveData +数据绑定 入门 在本教程中,我们将学习Android中的MVVM架构,我创建了示例项目来获取每个国家/地区的COVID19统计信息。 什么是MVVM架构? (MVVM)体系结构是...
ReactiveCocoa中文使用说明教程 ReactiveCocoa2实战 ReactiveCocoa 在github上有开源项目ReactiveCocoa2 1.0.3版本更新 再也不用担心奇葩的图文混排了 新增...
WPF开发教程.rar 目录 WPF基础入门 3 1. WPF基础之体系结构 3 2. WPF基础之XAML 9 3. WPF基础之基元素 23 4. WPF基础之属性系统 26 5. WPF基础之路由事件 33 6. WPF基础之布局系统 46 7. WPF基础之样式设置和模板化...
搜索远程作业 ...1-Kotlin2- MVVM设计模式3-改造2 4-滑翔5-导航组件6-安全Args 7- TabLayout 8-滑动刷新9- RecyclerView 10-视图绑定11-房间数据库12-协程13-由remotive.io为独立开发者提供的免费Api
Rx 教程 推荐 RxSwift进阶与实战 基于RxSwift的MVVMR架构(一)思想、基本原理及初步实现 一个基于MVVM架构模式的RxSwiftDemo,旨在掌握RxSwift较为进阶的内容 【漫谈】从项目实践走向RxSwift响应式函数编程 ...
1、Bootstrapper,Shell,Module,Region,Navigation使用 2、Prism工程结构 3、MVVM框架 4、页面导航
如果說jQuery是林志玲,那麼knockout.js可比陳妍希,同樣讓人一見傾心!! 這就是我初見knockout.js的感想。 knockout.js是一套JavaScript UI程式庫,主要用來... 支援IE6+, FF2, Chrome, Opera, Safari(含行動裝置版本)
安装教程 项目根目录build.gradle中添加 allprojects { repositories { ... maven { url '' } } } 2. 项目module中导入远程依赖 dependencies { implementation 'com.github.sujianchuan888:testAndroi:v0.0.5' } ...
它采用了MVVM(Model-View-ViewModel)模式,通过数据绑定和组件化的方式来实现高效、灵活的开发。 Vue具有以下优点和特点: 1. 渐进式框架:可以逐步应用到项目中,也可以整体引入使用。 2. 易学易用:文档完善、...
2、asp.net web api用于提供restful数据服务 3、fluentData新型轻量级ORM模型用于数据持久方案 4、log4net作为日志组件 5、json.net作为序列化组件 6、文档方案(均为开源) 导出:Excel2007使用EPPlus、Excel...
跳游戏这很简单,先这样再这样(= =哈哈哈,做的时候就各种红了)。这个项目是我上一年参加虎牙小程序比赛,留下的(不知道现在虎牙小...工具mvc或者mvvm框架,自己喜欢就行,用自己熟悉的。 PixiJS是一个超快的2D渲
1.历史由来 2.MVVM模式 3.数据驱动和组件式编程 4.Vue之Hello World! 5.生命周期 6.从Vue到页面 7.Vue组件的重要选项 8.Vue常用指令
Vue.js 是构建 Web 界面的 JavaScript 库,提供数据驱动的组件,还有简单灵活的 API,使得 MVVM 更简单。 主要特性: 可扩展的数据绑... 可视化JavaScript库Datav.js506 大数据时代的到来,对于...
Angular2 作为著名前端 MVVM 架构 Angular1 的继承者,从一定程度上说,引领了新一代 Web 前端开发技术的革新。从最新版的 ember.js, react.js, vue.js 中,可以看到这几种技术相互借鉴,取长补短,最终向一种技术...
其实就是类似于VUE REACT的 MVVM模式,专注于数据和逻辑。 小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。 框架提供了自己的视图层描述语言 WXML 和 WXSS,...
前言 Dagger 这个库的取名不仅仅来自它的本意“匕首”,同时也暗示了它的原理。...现在MVVM的data-binding还在实验阶段,传统的MVC框架Activity内部可能包含大量的代码,难以维护,现在主流的架构还是使用M