• 使用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.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 }

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

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

  • 相关阅读:
    【VUE3.0体验】关于路由的一些坑
    TensorFlow中的卷积函数
    TensorFlow源码安装
    ubuntu远程桌面
    TensorFlow图像处理API
    C程序员眼里的Python
    深度剖析HashMap的数据存储实现原理(看完必懂篇)
    golang 互斥锁和读写锁
    golang goroutine的调度
    golang channel的使用以及调度原理
  • 原文地址:https://www.cnblogs.com/zxbzl/p/2950050.html
Copyright © 2020-2023  润新知