使用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. 2年SQL Server DBA调优方面总结

    原文:2年SQL Server DBA调优方面总结 2年SQL Server DBA调优方面总结 当2年dba 我觉得,有些东西需要和大家分享探讨,先书单. 书单 1.<深入解析SQL Serv ...

  2. JavaScript权威指南科13章 webj浏览器avascript

    13.1 clientjavascript window对象是所有clientjavascript特点和api主要的接入点.它代表了一个浏览器窗口,通过window对象引用它. window 方法 a ...

  3. 探索Scala(1)-- 运算符重载

    Scala语言运算符重载全然是语法层面的小把戏,本文记录我对Scala语言运算符重载的一些理解. 方法调用语法糖 调用方法时,Scala同意省略点号和圆括号,如以下代码所看到的: 把运算符映射成单词 ...

  4. android 环境使用smack 必须注冊的组件

    // Private Data Storage pm.addIQProvider("query", "jabber:iq:private",new Privat ...

  5. ubuntu12.04下一个samba、tftp、nfs构造

    1.samba setting   1>apt-get install samba     apt-get install smbfs   2>mkdir /home/linux/shar ...

  6. CQRS模式实现

    [.NET领域驱动设计实战系列]专题十:DDD扩展内容:全面剖析CQRS模式实现 一.引言 前面介绍的所有专题都是基于经典的领域驱动实现的,然而,领域驱动除了经典的实现外,还可以基于CQRS模式来进行 ...

  7. 【LeetCode】 String中的最长回文

    java 普通版: 1.正序遍历数组,取得子字符串的首字母. 2.倒序遍历数组,取的子字符串的尾字母. (这样仅仅要在子循环中第一个出现回文,那么该回文肯定是本次循环的最长的回文) 3.新增数据结构, ...

  8. js 正则学习小记之匹配字符串优化篇

    原文:js 正则学习小记之匹配字符串优化篇 昨天在<js 正则学习小记之匹配字符串>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯 ...

  9. bigdata_hiveserver2报错_thrift

    问题一: php客户端,链接hiveserver2 ,报错 如下 1: server.TThreadPoolServer (TThreadPoolServer.java:run(215)) - Err ...

  10. git_自动同步_sync.sh

    1: 使用方法  sh sync.sh  code_dir 代码 #add echo $1 cd $1 git add . git commit -m "Added notes for $( ...