使用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. FPGA图案--数字表示(代码+波形)

    在数字逻辑系统,仅仅存在高低.所以用它只代表一个整数数字.并且有3代表性的种类.这是:原码表示(符号加绝对值值).反码表示(加-minus标志)而补码(符号加补).这三个在FPGA中都有着广泛的应用. ...

  2. 很酷的CSS3仿Facebook登录表单

    原文:很酷的CSS3仿Facebook登录表单 今天看到一款很不错的CSS3登录表单,外观是仿Facebook的登录表单,还挺不错的,另外也支持简单的表单输入框验证.下图是表单的效果图: 我们也可以在 ...

  3. AsyncTask来源分析(一)

    于android开发过程AsyncTask我会经常处理它.在网上,也有很多的其描述,因此,这里是不是说的用法,直接写自己的学习经验,以及它的一些浅显的认识,忘记错批评. AsyncTask它是一个抽象 ...

  4. 数字使用相应的加密策略传递一个字符串后Java实现代码

    公司采用公用电话传递数据,数据小于8整数位,为了确保安全,     在转移的过程中需要加密,加密规则如下面的:         第一个数据下降,附图然后各加5,和除以10的余数取代该数字,       ...

  5. hdu 亲和串(kmp)

    Problem Description 人随着岁数的增长是越大越聪明还是越大越笨,这是一个值得全世界科学家思考的问题,同样的问题Eddy也一直在思考,因为他在很小的时候就知道亲和串如何判断了,但是发现 ...

  6. c++的string容器

    c++相比c的一个好处就是实现了很多的容器和泛型算法,使得程序员的工作得到了很大的化简.其中一个很有用的泛型容器就是string.string是一个类,是一个在STL里边实现好了的类,由于他的很多功能 ...

  7. hdu1286 寻找新朋友 (欧拉功能)

    原标题:点击打开链接 关于欧拉函数的算法具体解说:点击打开链接 欧拉函数 1.欧拉函数是不全然积性函数. 2.欧拉函数p(x) = x * (p1 - 1) / p1 * (p2 - 1)/p2 * ...

  8. django中通过model名字获取model

    django1.6, 通过字符串和get_app.get_model获得对应的object 只需要两行代码: from django.db.models import get_model get_mo ...

  9. java io流之int数组数据的插入与取出

    java io流大家都非常熟悉吧,有时候假设用的不熟,对于数据的处理真的非常头疼,以下是对与int数组的处理. 以下是代码: public class Stream { private int a[] ...

  10. [ 夜间模式 ] NightVersion

    DKNightVersion框架.重写管理类 & 控件的分类!--可重写{ 使用GCD.runtime.delegate等 & 工具类的创建 } ================ 1. ...