打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
使用Prism实现的WPF MVVM点餐Demo

说明:本文出处:http://www.cnblogs.com/DebugLZQ/archive/2012/12/17/2821772.html

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

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

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

下面来实现它:

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

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

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

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

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

View Code
  1 View Code   2   3 <?xml version="1.0" encoding="utf-8"?>  4 <Dishes>  5     <Dish>  6         <Name>土豆泥底披萨</Name>  7         <Category>披萨</Category>  8         <Comment>本店特色</Comment>  9         <Score>4.5</Score> 10     </Dish> 11     <Dish> 12         <Name>烤囊底披萨</Name> 13         <Category>披萨</Category> 14         <Comment>本店特色</Comment> 15         <Score>5</Score> 16     </Dish> 17     <Dish> 18         <Name>水果披萨</Name> 19         <Category>披萨</Category> 20         <Comment></Comment> 21         <Score>4</Score> 22     </Dish> 23     <Dish> 24         <Name>牛肉披萨</Name> 25         <Category>披萨</Category> 26         <Comment></Comment> 27         <Score>5</Score> 28     </Dish> 29     <Dish> 30         <Name>培根披萨</Name> 31         <Category>披萨</Category> 32         <Comment></Comment> 33         <Score>4.5</Score> 34     </Dish> 35     <Dish> 36         <Name>什锦披萨</Name> 37         <Category>披萨</Category> 38         <Comment></Comment> 39         <Score>4.5</Score> 40     </Dish> 41     <Dish> 42         <Name>金枪鱼披萨</Name> 43         <Category>披萨</Category> 44         <Comment></Comment> 45         <Score>5</Score> 46     </Dish> 47     <Dish> 48         <Name>海鲜披萨</Name> 49         <Category>披萨</Category> 50         <Comment></Comment> 51         <Score>5</Score> 52     </Dish> 53     <Dish> 54         <Name>川香披萨</Name> 55         <Category>披萨</Category> 56         <Comment></Comment> 57         <Score>4.5</Score> 58     </Dish> 59     <Dish> 60         <Name>黑椒鸡腿扒</Name> 61         <Category>特色主食</Category> 62         <Comment>本店特色</Comment> 63         <Score>5</Score> 64     </Dish> 65     <Dish> 66         <Name>肉酱意面</Name> 67         <Category>特色主食</Category> 68         <Comment>本店特色</Comment> 69         <Score>5</Score> 70     </Dish> 71     <Dish> 72         <Name>寂寞小章鱼</Name> 73         <Category>风味小吃</Category> 74         <Comment></Comment> 75         <Score>5</Score> 76     </Dish> 77     <Dish> 78         <Name>照烧鸡软骨</Name> 79         <Category>风味小吃</Category> 80         <Comment></Comment> 81         <Score>5</Score> 82     </Dish> 83     <Dish> 84         <Name>芝士青贝</Name> 85         <Category>风味小吃</Category> 86         <Comment></Comment> 87         <Score>4.5</Score> 88     </Dish> 89     <Dish> 90         <Name>奥尔良烤翅</Name> 91         <Category>风味小吃</Category> 92         <Comment>秒杀KFC</Comment> 93         <Score>5</Score> 94     </Dish> 95     <Dish> 96         <Name>双酱煎泥肠</Name> 97         <Category>风味小吃</Category> 98         <Comment></Comment> 99         <Score>4</Score>100     </Dish>101     <Dish>102         <Name>香酥鱿鱼圈</Name>103         <Category>风味小吃</Category>104         <Comment>本店特色</Comment>105         <Score>4.5</Score>106     </Dish>107     <Dish>108         <Name>黄金蝴蝶虾</Name>109         <Category>风味小吃</Category>110         <Comment>本店特色</Comment>111         <Score>5</Score>112     </Dish>113     <Dish>114         <Name>金枪鱼沙拉</Name>115         <Category>沙拉</Category>116         <Comment>本店特色</Comment>117         <Score>5</Score>118     </Dish>119     <Dish>120         <Name>日式素沙拉</Name>121         <Category>沙拉</Category>122         <Comment></Comment>123         <Score>5</Score>124     </Dish>125     <Dish>126         <Name>冰糖洛神</Name>127         <Category>饮料</Category>128         <Comment></Comment>129         <Score>5</Score>130     </Dish>131     <Dish>132         <Name>玫瑰特饮</Name>133         <Category>饮料</Category>134         <Comment></Comment>135         <Score>5</Score>136     </Dish>137     <Dish>138         <Name>清新芦荟</Name>139         <Category>饮料</Category>140         <Comment></Comment>141         <Score>5</Score>142     </Dish>143     <Dish>144         <Name>薄荷汽水</Name>145         <Category>饮料</Category>146         <Comment>本店特色</Comment>147         <Score>5</Score>148     </Dish>149 </Dishes>

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

View Code
 1 View Code  2  3 namespace WpfPrism.Models 4 { 5     class Dish 6     { 7         public string Name { get; set; } 8  9         public string Category { get; set; }10 11         public string  Comment { get; set; }12 13         public string  Score { get; set; }14     }15 }
View Code
 1 View Code  2  3 namespace WpfPrism.Models 4 { 5     class Restaurant 6     { 7         public string Name { get; set; } 8  9         public string Address { get; set; }10 11         public string  PhoneNumber { get; set; }12     }13 }
View Code
 1 View Code  2  3 namespace WpfPrism.Models 4 { 5     class Restaurant 6     { 7         public string Name { get; set; } 8  9         public string Address { get; set; }10 11         public string  PhoneNumber { get; set; }12     }13 }

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

View Code
 1 View Code  2  3 using System.Collections.Generic; 4 using WpfPrism.Models; 5  6 namespace WpfPrism.Services 7 { 8     interface IDataService 9     {10         List<Dish> GetAllDishes();11     }12 }
View Code
 1 View Code  2  3 using System; 4 using System.Collections.Generic; 5 using WpfPrism.Models; 6 using System.IO; 7 using System.Xml.Linq; 8  9 10 namespace WpfPrism.Services11 {12     class XMLDataService:IDataService//接口:定义和实现相分离13     {14         #region IDataService 成员15 16         public List<Models.Dish> GetAllDishes()17         {18             List<Dish> dishList = new List<Dish>();19 20             string xmlFile = Path.Combine(Environment.CurrentDirectory, @"Data/Data.xml");21 22             XDocument xDoc = XDocument.Load(xmlFile);23             var dishes = xDoc.Descendants("Dish");24             foreach (var d in dishes)25             {26                 Dish dish = new Dish();27                 dish.Name = d.Element("Name").Value;28                 dish.Category = d.Element("Category").Value;29                 dish.Comment = d.Element("Comment").Value;30                 dish.Score = d.Element("Score").Value;31                 dishList.Add(dish);32             }33 34             return dishList;35         }36 37         #endregion38     }39 }
View Code
 1 View Code  2  3 using System.Collections.Generic; 4  5 namespace WpfPrism.Services 6 { 7     interface IOrderService 8     { 9         void PlaceOrder(List<string> dishes);10     }11 }
View Code
 1 View Code  2  3 using System.Collections.Generic; 4 using System.IO; 5  6 namespace WpfPrism.Services 7 { 8     class MockOrderService:IOrderService//接口:实现定义和实现相分离 9     {10         #region IOrderService 成员11 12         public void PlaceOrder(List<string> dishes)13         {14             File.WriteAllLines(@"D:/order.txt", dishes.ToArray());15         }16 17         #endregion18     }19 }

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

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

View Code
 1 using Microsoft.Practices.Prism.ViewModel; 2 using WpfPrism.Models; 3  4 namespace WpfPrism.ViewModels 5 { 6     class DishMenuItemViewModel:NotificationObject 7     { 8         public Dish Dish { get; set; } 9 10         private bool isSelected;11         public bool IsSelected//这个地方刚开始写错了,废了太大的劲才找出来(注意拼写!)12         {13             get { return isSelected; }14             set 15             {16                 isSelected = value;17                 RaisePropertyChanged("IsSelected");18             }19         }20     }21 }
View Code
 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using Microsoft.Practices.Prism.ViewModel; 5 using WpfPrism.Models; 6 using WpfPrism.Services; 7 using Microsoft.Practices.Prism.Commands; 8 using System.Windows; 9 10 namespace WpfPrism.ViewModels11 {12     class MianWindowViewModel:NotificationObject13     {14         private Restaurant restaurant;15         public Restaurant Restaurant16         {17             get { return restaurant; }18             set19             {20                 restaurant = value;21                 RaisePropertyChanged("Restaurant");22             }23         }24 25         //外加的一个属性,点菜的数量26         private int count;27         public int Count28         {29             get { return count; }30             set31             {32                 count = value;33                 RaisePropertyChanged("Count");34             }35         }36 37         private List<DishMenuItemViewModel> dishMenu;38         public List<DishMenuItemViewModel> DishMenu39         {40             get { return dishMenu; }41             set42             {43                 dishMenu = value;44                 RaisePropertyChanged("DishMenu");45             }46         }47 48         public MianWindowViewModel()49         {50             LoadRestuarant();//赋值Restaurant属性51             LoadDishMenu();//赋值DishMenu属性52 53             //初始化两个命令属性54             PlaceOrderCommand = new DelegateCommand(new Action(PlaceOrderCommandExecute));55             SelectMenuItemCommand = new DelegateCommand(new Action(SelectMenuItemCommandExecute));56         }57 58         private void LoadRestuarant()59         {60             Restaurant = new Restaurant() {Name="百年苏韵", Address="江苏大学", PhoneNumber="0511-12345678"};           61         }62 63         private void LoadDishMenu()64         {65             DishMenu = new List<DishMenuItemViewModel>();66 67             IDataService ds = new XMLDataService();68             var dishes = ds.GetAllDishes();69             foreach (var d in dishes)70             {71                 DishMenuItemViewModel item = new DishMenuItemViewModel() {  Dish=d};72                 DishMenu.Add(item);73             }74         }75 76         //两个命令属性77         public DelegateCommand PlaceOrderCommand { get; set; }78         public DelegateCommand SelectMenuItemCommand { get; set; }79 80         private void PlaceOrderCommandExecute()81         {82             //获取点菜单83             var selectedDishes = dishMenu.Where(d => d.IsSelected == true).Select(d => d.Dish.Name).ToList();84 85             //仅保存到本地磁盘--可以写一些有意义的代码86             IOrderService orderService = new MockOrderService();87             orderService.PlaceOrder(selectedDishes );88 89             MessageBox.Show("订餐成功!");90         }91 92         private void SelectMenuItemCommandExecute()93         {94             Count = DishMenu.Count(n=>n.IsSelected==true);95         }96         97     }98 }

注意NotificationObject是ViewModel的基类。

最后,为View添加Binding:

View Code
 1 <Window x:Class="WpfPrism.MainWindow" 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4         Title="MainWindow" Height="350" Width="590"> 5     <Grid> 6         <Grid.RowDefinitions> 7             <RowDefinition Height="Auto"/> 8             <RowDefinition Height="*"/> 9             <RowDefinition Height="Auto"/>10         </Grid.RowDefinitions>11         <!-- 餐馆信息-->12         <StackPanel Grid.Row="0">13             <StackPanel Orientation="Horizontal" >14                 <TextBlock Text="欢迎光临-" FontSize="40"/>15                 <TextBlock Text="{Binding Restaurant.Name}" FontSize="40"  Foreground="HotPink" />16             </StackPanel>17             <StackPanel Orientation="Horizontal" >18                 <TextBlock Text="地址:" FontSize="40"/>19                 <TextBlock Text="{Binding Restaurant.Address}" FontSize="40" Foreground="HotPink" />20             </StackPanel>21             <StackPanel Orientation="Horizontal" >22                 <TextBlock Text="电话:" FontSize="40"/>23                 <TextBlock Text="{Binding Restaurant.PhoneNumber}" FontSize="40" Foreground="HotPink" />24             </StackPanel>25         </StackPanel>26         <!--菜品信息,选菜-->27         <DataGrid Grid.Row="1" ItemsSource="{Binding DishMenu}" AutoGenerateColumns="False" GridLinesVisibility="All" CanUserDeleteRows="False" CanUserAddRows="False" >28             <DataGrid.Columns>29                 <!-- 这4个来自(ViewModel )Dish属性,UI上一次读出,不会变-->30                 <DataGridTextColumn Header="菜名"  Binding="{Binding Dish.Name}" Width="120"/>31                 <DataGridTextColumn Header="种类"  Binding="{Binding Dish.Category}" Width="120"/>32                 <DataGridTextColumn Header="点评"  Binding="{Binding Dish.Comment}" Width="120"/>33                 <DataGridTextColumn Header="推荐指数"  Binding="{Binding Dish.Score}" Width="120"/>34                 <!--注意这个属性-->35                 <DataGridTemplateColumn Header="选中" SortMemberPath="IsSelected" Width="120">36                     <DataGridTemplateColumn.CellTemplate>37                         <DataTemplate >38                             <CheckBox IsChecked="{Binding Path=IsSelected,UpdateSourceTrigger=PropertyChanged}"39                                       VerticalAlignment="Center" HorizontalAlignment="Center" 40                                       Command="{Binding Path=DataContext.SelectMenuItemCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"/>41                         </DataTemplate>42                     </DataGridTemplateColumn.CellTemplate>43                 </DataGridTemplateColumn>44             </DataGrid.Columns>45         </DataGrid>46         <!--所点菜品个数,点菜-->47         <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" >48             <TextBlock Text="点了几个菜?" TextAlignment="Center"  />49             <TextBox IsReadOnly="True" Text="{Binding Count}" Width="120" TextAlignment="Center" />50             <Button Content="点菜" Command="{Binding PlaceOrderCommand}"/>51         </StackPanel>52     </Grid>53 </Window>
View Code
 1 using System.Windows; 2 using WpfPrism.ViewModels; 3  4 namespace WpfPrism 5 { 6     /// <summary> 7     /// MainWindow.xaml 的交互逻辑 8     /// </summary> 9     public partial class MainWindow : Window10     {11         public MainWindow()12         {13             InitializeComponent();14 15             this.DataContext = new MianWindowViewModel();16         }17     }18 }

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

心得:学习Prism MVVM唯一的方法就是多看优秀的代码、多写代码、多多思考,才能理解其模式原理!

posted @ 2013-03-08 15:27 银河系上的地球 阅读(177) 评论(1) 编辑 收藏

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Binding Input Parameters
XML 和 Java 技术:数据绑定,第 4 部分: 使用 JiBX
用IComparable和IComparable<T>接口实现两个类对象的比较大小.
structure
LINQ操作符二:SelectMany
mysql错误:Column 'id' in field list is ambiguous的解决方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服