使用Prism实现的WPF MVVM点餐Demo

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

使用Prism实现的WPF MVVM点餐Demo

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

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

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

下面来实现它:

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

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

使用Prism实现的WPF MVVM点餐Demo

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

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

使用Prism实现的WPF MVVM点餐Demo

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.Services

11 {

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         #endregion

38     }

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         #endregion

18     }

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.ViewModels

11 {

12     class MianWindowViewModel:NotificationObject

13     {

14         private Restaurant restaurant;

15         public Restaurant Restaurant

16         {

17             get { return restaurant; }

18             set

19             {

20                 restaurant = value;

21                 RaisePropertyChanged("Restaurant");

22             }

23         }

24 

25         //外加的一个属性,点菜的数量

26         private int count;

27         public int Count

28         {

29             get { return count; }

30             set

31             {

32                 count = value;

33                 RaisePropertyChanged("Count");

34             }

35         }

36 

37         private List<DishMenuItemViewModel> dishMenu;

38         public List<DishMenuItemViewModel> DishMenu

39         {

40             get { return dishMenu; }

41             set

42             {

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 : Window

10     {

11         public MainWindow()

12         {

13             InitializeComponent();

14 

15             this.DataContext = new MianWindowViewModel();

16         }

17     }

18 }

使用Prism实现的WPF MVVM点餐Demo

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

使用Prism实现的WPF MVVM点餐Demo

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

你可能感兴趣的:(demo)