使用Prism提供的类实现WPF MVVM点餐Demo

由于公司开发的技术需求,近期在学习MVVM模式开发WPF应用程序。进过一段时间的学习,感受到:学习MVVM模式,最好的方法就是用MVVM做几个Demo,因为编程里面的东西还是原来的WPF的相关知识。最近学习的资料来源大多为CodePlex、CodeProject和MSDN,以及博客园MS的MVP刘铁锰的一些资料。

前面几篇博文DebugLZQ写了,如何来写MVVM,以及Prism框架的安装等等。

本篇在前面的基础上,通过一个相对复杂一点的Demo,来学习Prism中的一些类的使用。

首先来介绍下今天这个Demo要实现的功能,今天开启的系统是XP,所以下面各位看到的将是XP风格的界面。:

·界面上方TextBlock显示餐馆的信息(粉红色字),该信息保存在一个ViewModel的一个餐馆的属性中。

·DataGrid显示菜品信息,从一个模拟的Service中读出;并在最后添加一个CheckBox Binding一个命令用来选择菜品

·下面的TextBox显示选中了几个菜,Button则Binding一个Command实现点菜(象征性的存入本地磁盘)

下面来实现它:

//---------------------

最终的项目的文件结构如下:

前面说过,可以直接饮用Prism,只引入相关的程序集也可以(虽然是一回事),这次我们就这么干!

1.新建一个WpfPrism的WPF项目,添加Prism dll引用,(使用NotificationObject、DelegateCommand)如下:

2.在项目中添加一个Data文件夹,放入Data.XML文件,文件如下:


3.在项目中添加Model文件夹。添加两个Model Dish和Restaurant,分别如下:

4.在项目中添加Services文件夹,其中IDataService、XMLDataService用来定义和实现:获取菜品信息功能。IOrderService和MockOrderService用来定义和实现:点菜功能。之所以使用接口,是为了定义和实现相分离!
其代码依次如下:

5.在项目中添加一个ViewModels文件夹,并添加两个Model:DishMenuItemViewModel和MianWindowViewModel。

稍微解释一下:MianWindowViewModel中的一个属性是List<MianWindowViewModel>类型的。两者代码分别如下:

using Microsoft.Practices.Prism.ViewModel;
using WpfPrism.Models; namespace WpfPrism.ViewModels
{
class DishMenuItemViewModel:NotificationObject
{
public Dish Dish { get; set; } private bool isSelected;
public bool IsSelected//这个地方刚开始写错了,废了太大的劲才找出来(注意拼写!)
{
get { return isSelected; }
set
{
isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Prism.ViewModel;
using WpfPrism.Models;
using WpfPrism.Services;
using Microsoft.Practices.Prism.Commands;
using System.Windows; namespace WpfPrism.ViewModels
{
class MianWindowViewModel:NotificationObject
{
private Restaurant restaurant;
public Restaurant Restaurant
{
get { return restaurant; }
set
{
restaurant = value;
RaisePropertyChanged("Restaurant");
}
} //外加的一个属性,点菜的数量
private int count;
public int Count
{
get { return count; }
set
{
count = value;
RaisePropertyChanged("Count");
}
} private List<DishMenuItemViewModel> dishMenu;
public List<DishMenuItemViewModel> DishMenu
{
get { return dishMenu; }
set
{
dishMenu = value;
RaisePropertyChanged("DishMenu");
}
} public MianWindowViewModel()
{
LoadRestuarant();//赋值Restaurant属性
LoadDishMenu();//赋值DishMenu属性 //初始化两个命令属性
PlaceOrderCommand = new DelegateCommand(new Action(PlaceOrderCommandExecute));
SelectMenuItemCommand = new DelegateCommand(new Action(SelectMenuItemCommandExecute));
} private void LoadRestuarant()
{
Restaurant = new Restaurant() {Name="百年苏韵", Address="江苏大学", PhoneNumber="0511-12345678"};
} private void LoadDishMenu()
{
DishMenu = new List<DishMenuItemViewModel>(); IDataService ds = new XMLDataService();
var dishes = ds.GetAllDishes();
foreach (var d in dishes)
{
DishMenuItemViewModel item = new DishMenuItemViewModel() { Dish=d};
DishMenu.Add(item);
}
} //两个命令属性
public DelegateCommand PlaceOrderCommand { get; set; }
public DelegateCommand SelectMenuItemCommand { get; set; } private void PlaceOrderCommandExecute()
{
//获取点菜单
var selectedDishes = dishMenu.Where(d => d.IsSelected == true).Select(d => d.Dish.Name).ToList(); //仅保存到本地磁盘--可以写一些有意义的代码
IOrderService orderService = new MockOrderService();
orderService.PlaceOrder(selectedDishes ); MessageBox.Show("订餐成功!");
} private void SelectMenuItemCommandExecute()
{
Count = DishMenu.Count(n=>n.IsSelected==true);
} }
}

注意NotificationObject是ViewModel的基类。

最后,为View添加Binding:

<Window x:Class="WpfPrism.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="590">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 餐馆信息-->
<StackPanel Grid.Row="0">
<StackPanel Orientation="Horizontal" >
<TextBlock Text="欢迎光临-" FontSize="40"/>
<TextBlock Text="{Binding Restaurant.Name}" FontSize="40" Foreground="HotPink" />
</StackPanel>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="地址:" FontSize="40"/>
<TextBlock Text="{Binding Restaurant.Address}" FontSize="40" Foreground="HotPink" />
</StackPanel>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="电话:" FontSize="40"/>
<TextBlock Text="{Binding Restaurant.PhoneNumber}" FontSize="40" Foreground="HotPink" />
</StackPanel>
</StackPanel>
<!--菜品信息,选菜-->
<DataGrid Grid.Row="1" ItemsSource="{Binding DishMenu}" AutoGenerateColumns="False" GridLinesVisibility="All" CanUserDeleteRows="False" CanUserAddRows="False" >
<DataGrid.Columns>
<!-- 这4个来自(ViewModel )Dish属性,UI上一次读出,不会变-->
<DataGridTextColumn Header="菜名" Binding="{Binding Dish.Name}" Width="120"/>
<DataGridTextColumn Header="种类" Binding="{Binding Dish.Category}" Width="120"/>
<DataGridTextColumn Header="点评" Binding="{Binding Dish.Comment}" Width="120"/>
<DataGridTextColumn Header="推荐指数" Binding="{Binding Dish.Score}" Width="120"/>
<!--注意这个属性-->
<DataGridTemplateColumn Header="选中" SortMemberPath="IsSelected" Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<CheckBox IsChecked="{Binding Path=IsSelected,UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Command="{Binding Path=DataContext.SelectMenuItemCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<!--所点菜品个数,点菜-->
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" >
<TextBlock Text="点了几个菜?" TextAlignment="Center" />
<TextBox IsReadOnly="True" Text="{Binding Count}" Width="120" TextAlignment="Center" />
<Button Content="点菜" Command="{Binding PlaceOrderCommand}"/>
</StackPanel>
</Grid>
</Window>
using System.Windows;
using WpfPrism.ViewModels; namespace WpfPrism
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); this.DataContext = new MianWindowViewModel();
}
}
}

程序运行如下:

可以在D盘找到如下的txt文件:

也请参考CodeProject:WPF Master Details MVVM Application

说明:本文使用Prism框架中的几个类,来简化MVVM的编写。并未所见标准Prism的Bootstrapper、Shell、Region、Module、Unity/MEF...

关于Prism框架的知识,请关注DebugLZQ后续博文:

Prism框架-Hello Prism Using Unity

Hello Prism Using MEF

没什么高端的知识,老鸟绕过轻拍~

希望对你有帮助~

 

使用Prism提供的类实现WPF MVVM点餐Demo的更多相关文章

  1. .NET Core 3 WPF MVVM框架 Prism系列之命令

    本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的命令的用法 一.创建DelegateCommand命令 我们在上一篇.NET Core 3 WPF MVVM框架 Prism系列之 ...

  2. .NET Core 3 WPF MVVM框架 Prism系列之导航系统

    本文将介绍如何在.NET Core3环境下使用MVVM框架Prism基于区域Region的导航系统 在讲解Prism导航系统之前,我们先来看看一个例子,我在之前的demo项目创建一个登录界面: 我们看 ...

  3. 1: 介绍Prism5.0 Introduction to the Prism Library 5.0 for WPF(英汉对照版)

     Prism provides guidance designed to help you more easily design and build rich, flexible, and easy- ...

  4. .NET Core 3 WPF MVVM框架 Prism系列之模块化

    本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的应用程序的模块化 前言  我们都知道,为了构成一个低耦合,高内聚的应用程序,我们会分层,拿一个WPF程序来说,我们通过MVVM模式 ...

  5. .NET Core 3 WPF MVVM框架 Prism系列之事件聚合器

    本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 一.事件聚合器  在上一篇 .NET Core 3 WPF MVVM框架 Prism系列之模块化 ...

  6. WPF MVVM 从Prism中学习设计模式之Event Aggregator 模式

    Prism简介 Prism是由微软Patterns & Practices团队开发的项目,目的在于帮助开发人员构建松散耦合的.更灵活.更易于维护并且更易于测试的WPF应用或是Silverlig ...

  7. .NET Core 3 WPF MVVM框架 Prism系列之对话框服务

     本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的对话框服务,这也是prism系列的最后一篇完结文章,下面是Prism系列文章的索引: .NET Core 3 WPF MVVM框 ...

  8. .NET Core 3 WPF MVVM框架 Prism系列文章索引

    .NET Core 3 WPF MVVM框架 Prism系列之数据绑定 .NET Core 3 WPF MVVM框架 Prism系列之命令 .NET Core 3 WPF MVVM框架 Prism系列 ...

  9. WPF/MVVM 快速开始指南(译)(转)

    WPF/MVVM 快速开始指南(译) 本篇文章是Barry Lapthorn创作的,感觉写得很好,翻译一下,做个纪念.由于英文水平实在太烂,所以翻译有错或者译得不好的地方请多指正.另外由于原文是针对W ...

随机推荐

  1. [ExtJS5学习笔记]第22 Extjs5正在使用beforeLabelTpl添加所需的配置选项标注星号标记

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39395753 官方样例:http://docs.sencha.com/extjs/5. ...

  2. redis和redis php扩展安装(转)

    redis是一个内存数据库,比memcache支持更丰富的value类型,新浪微博就使用redis来做缓存. redis的源码安装 wget http://download.redis.io/redi ...

  3. android怎么在launcher改动内置apk的icon

    找到launcher下的IconCache中加入变量用来存储要改动apk的包名 及要改动成的icon private String[] className = {"com.google.an ...

  4. nettyclient异步获取数据

    源代码见,以下主要是做个重要代码记录 http://download.csdn.net/detail/json20080301/8180351 NETTYclient获取数据採用的方式是异步获取数据, ...

  5. POJ 2777 Count Color(段树)

    职务地址:id=2777">POJ 2777 我去.. 延迟标记写错了.标记到了叶子节点上.. . . 这根本就没延迟嘛.. .怪不得一直TLE... 这题就是利用二进制来标记颜色的种 ...

  6. Angularjs里面跨作用域

    Angularjs里面跨作用域的实战!   好久没有来写博客了,最近一直在用Google的AngularJS,后面我自己简称AngularJS就叫AJ吧! 学习AngularJS一路也是深坑颇多啊-- ...

  7. Swift: 打造滑动解锁文字动画

    原文:Swift: 打造滑动解锁文字动画 最近木事,找出来玩了玩facebook的paper.到处都是那个"slide to unlock your phone"的效果啊.忽闪忽闪 ...

  8. JAVA深入研究——Method的Invoke方法(转)

    在写代码的时候,发现Method可以调用子类的对象,但子类即使是改写了的Method,方法名一样,去调用父类的对象也会报错,虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java ...

  9. Firefox firebug and xpath checker

    From http://blog.sina.com.cn/s/blog_5aefba9a0100csy8.html

  10. Oracle表空间及分区表

    (1) 表空间及分区表的概念表空间: 是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间.分区表: 当表中的数据量不断增大,查询数据的速度就会变慢,应 ...