说明:本文出处: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文件,文件如下:
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,分别如下:
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 }
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 }
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用来定义和实现:点菜功能。之所以使用接口,是为了定义和实现相分离!
其代码依次如下:
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 }
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 }
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 }
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>类型的。两者代码分别如下:
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 }
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:
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>
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 }
可以在D盘找到如下的txt文件:
心得:学习Prism MVVM唯一的方法就是多看优秀的代码、多写代码、多多思考,才能理解其模式原理!