《深入浅出WPF》学习笔记七.使用Prism实现Mvvm点单系统
背景
深入浅出Wpf系列视频的最后一个demo,使用Prism、Mvvm实现点单系统。demo并不复杂,但是涉及的面广,方便更好的理解wpf。代码在下面自取。后续会把git地址补充上来。
代码
项目层级
command
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace RestaurantOrderSystem.Command
{
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
public RelayCommand(Action<object> execute)
{
_execute = execute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
Data
<?xml version="1.0" encoding="utf-8" ?>
<Dishes>
<Dish>
<Name>奥尔良烤肉披萨</Name>
<Category>披萨</Category>
<Comment>本店推荐</Comment>
<Score>4.5</Score>
</Dish>
<Dish>
<Name>夏威夷风情披萨</Name>
<Category>披萨</Category>
<Comment>本店推荐</Comment>
<Score>4.6</Score>
</Dish>
<Dish>
<Name>榴莲卷边披萨</Name>
<Category>披萨</Category>
<Comment>本店推荐</Comment>
<Score>4.7</Score>
</Dish>
<Dish>
<Name>韩式烤肉披萨</Name>
<Category>披萨</Category>
<Comment>特色</Comment>
<Score>4.5</Score>
</Dish>
<Dish>
<Name>墨尔本牛排</Name>
<Category>牛排</Category>
<Comment>本店推荐</Comment>
<Score>4.6</Score>
</Dish>
<Dish>
<Name>德克萨斯牛排</Name>
<Category>牛排</Category>
<Comment>本店推荐</Comment>
<Score>4.6</Score>
</Dish>
<Dish>
<Name>纽约香煎牛排</Name>
<Category>牛排</Category>
<Comment>本店推荐</Comment>
<Score>4.6</Score>
</Dish>
<Dish>
<Name>可乐</Name>
<Category>饮料</Category>
<Comment>本店推荐</Comment>
<Score>4.6</Score>
</Dish>
<Dish>
<Name>雪碧</Name>
<Category>饮料</Category>
<Comment>本店推荐</Comment>
<Score>4.6</Score>
</Dish>
</Dishes>
Models
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RestaurantOrderSystem.Models
{
public class Dish
{
public string Name { get; set; }
public string Category { get; set; }
public string Comment { get; set; }
public double Score { get; set; }
public override string ToString()
{
return string.Format("{0},{1},{2},{3}", Name, Category, Comment, Score);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RestaurantOrderSystem.Models
{
public class Restaurant
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
}
Services
using RestaurantOrderSystem.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RestaurantOrderSystem.Services
{
internal interface IDataService
{
public List<Dish> GetDishes();
}
}
using RestaurantOrderSystem.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RestaurantOrderSystem.Services
{
public interface IOrderService
{
public void PlaceOrder(List<Dish> dishes);
}
}
using RestaurantOrderSystem.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RestaurantOrderSystem.Services
{
public class MockOrderService : IOrderService
{
public void PlaceOrder(List<Dish> dishes)
{
string xmlFile = System.IO.Path.Combine(Environment.CurrentDirectory, @"Data\Order.txt");
if (!File.Exists(xmlFile)) { File.Create(xmlFile); }
System.IO.File.WriteAllLines(xmlFile, dishes.AsEnumerable().Select(o => o.Name.ToString()).ToArray());
}
}
}
using RestaurantOrderSystem.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;
namespace RestaurantOrderSystem.Services
{
internal class XmlDataService : IDataService
{
public List<Dish> GetDishes()
{
List<Dish> disheList = new List<Dish>();
string xmlFile = System.IO.Path.Combine(Environment.CurrentDirectory, @"Data\Data.xml");
XDocument xmlDoc = XDocument.Load(xmlFile);
var dishes = xmlDoc.Descendants("Dish");
Dish dish = null;
foreach (var item in dishes)
{
dish = new Dish();
dish.Name = item.Element("Name")?.Value;
dish.Category = item.Element("Category")?.Value;
dish.Comment = item.Element("Comment")?.Value;
dish.Score = Convert.ToDouble(item.Element("Score")?.Value);
disheList.Add(dish);
}
return disheList;
}
}
}
ViewModels
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Mvvm;
using RestaurantOrderSystem.Models;
namespace RestaurantOrderSystem.ViewModels
{
public class DishMenuItemViewModel :BindableBase
{
public Dish Dish { get; set; }
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set { SetProperty(ref isSelected, value); }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Prism.Mvvm;
using Prism.Regions;
using RestaurantOrderSystem.Command;
using RestaurantOrderSystem.Models;
using RestaurantOrderSystem.Services;
namespace RestaurantOrderSystem.ViewModels
{
public class OrderViewModel : BindableBase
{
private int count;
public int Count
{
get { return count; }
set
{
SetProperty(ref count, value);
}
}
private List<DishMenuItemViewModel> menuItem;
public List<DishMenuItemViewModel> MenuItem
{
get { return menuItem; }
set
{
SetProperty(ref menuItem, value);
}
}
private Restaurant myRestaurant;
public Restaurant MyRestaurant
{
get { return myRestaurant; }
set
{
SetProperty(ref myRestaurant, value);
}
}
public OrderViewModel()
{
orderService = new MockOrderService();
xmlDataService = new XmlDataService();
LoadRestaurant();
LoadMenuData();
Count = 0;
}
private void LoadRestaurant()
{
Restaurant restaurant = new Restaurant();
restaurant.Name = "JokerRestaurant";
restaurant.Address = "上海世纪汇";
restaurant.Phone = "024-25978888";
this.MyRestaurant = restaurant;
}
private MockOrderService orderService;
private XmlDataService xmlDataService;
private void LoadMenuData()
{
List<Dish> dishes = xmlDataService.GetDishes();
List<DishMenuItemViewModel> dishMenuList = new List<DishMenuItemViewModel>();
foreach (Dish dish in dishes)
{
DishMenuItemViewModel dishMenu = new DishMenuItemViewModel();
dishMenu.Dish = dish;
dishMenu.IsSelected = false;
dishMenuList.Add(dishMenu);
}
this.MenuItem = dishMenuList;
}
private RelayCommand placeOrderCommand;
public RelayCommand PlaceOrderCommand
{
get
{
if (placeOrderCommand == null)
placeOrderCommand = new RelayCommand(PlaceOrderCommandExecute);
return placeOrderCommand;
}
set { placeOrderCommand = value; }
}
private void PlaceOrderCommandExecute(object param)
{
var orderMenu = this.MenuItem.Where(o => o.IsSelected == true).Select(o => o.Dish).ToList();
orderService.PlaceOrder(orderMenu);
MessageBox.Show("下单成功!");
}
private RelayCommand selectMenuItemCommand;
public RelayCommand SelectMenuItemCommand
{
get
{
if (selectMenuItemCommand == null)
selectMenuItemCommand = new RelayCommand(SelectMenuItemCommandExecute);
return selectMenuItemCommand;
}
set { selectMenuItemCommand = value; }
}
private void SelectMenuItemCommandExecute(object param)
{
this.Count = this.MenuItem.Where(o => o.IsSelected == true).Count();
}
}
}
Views
<Window x:Class="RestaurantOrderSystem.Views.OrderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RestaurantOrderSystem.Views"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
Title="{Binding MyRestaurant.Name,StringFormat=\{0\}-在线订餐}" Height="600" Width="1000">
<Border BorderBrush="Orange" BorderThickness="3" Background="Yellow" CornerRadius="6">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Border BorderBrush="Orange" BorderThickness="1" Background="Yellow" CornerRadius="6" Padding="4" >
<StackPanel Grid.Row="0">
<StackPanel Orientation="Horizontal">
<StackPanel.Effect>
<DropShadowEffect Color="LightGray"></DropShadowEffect>
</StackPanel.Effect>
<TextBlock Text="欢迎光临-" FontSize="60" FontFamily="LiShu"></TextBlock>
<TextBlock Text="{Binding MyRestaurant.Name}" FontSize="60" FontFamily="LiShu"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="店铺地址-" FontSize="24" FontFamily="LiShu"></TextBlock>
<TextBlock Text="{Binding MyRestaurant.Address}" FontSize="24" FontFamily="LiShu"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="订餐电话-" FontSize="24" FontFamily="LiShu"></TextBlock>
<TextBlock Text="{Binding MyRestaurant.Phone}" FontSize="24" FontFamily="LiShu"></TextBlock>
</StackPanel>
</StackPanel>
</Border>
<DataGrid AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding MenuItem}"
Grid.Row="1" Margin="0,4" GridLinesVisibility="None" FontSize="16">
<DataGrid.Columns>
<DataGridTextColumn Header="菜品" Width="120" Binding="{Binding Dish.Name}"></DataGridTextColumn>
<DataGridTextColumn Header="种类" Width="120" Binding="{Binding Dish.Category}"></DataGridTextColumn>
<DataGridTextColumn Header="点评" Width="120" Binding="{Binding Dish.Comment}"></DataGridTextColumn>
<DataGridTextColumn Header="推荐分数" Width="120" Binding="{Binding Dish.Score}"></DataGridTextColumn>
<DataGridTemplateColumn Header="选中" SortMemberPath="IsSelected" Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Width="120" IsChecked="{Binding Path=IsSelected,UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Command="{Binding Path=DataContext.SelectMenuItemCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="1">
<TextBlock Text="总计" HorizontalAlignment="Center"></TextBlock>
<TextBox IsEnabled="False" Text="{Binding Count}" Margin="4,0" Width="120"></TextBox>
<Button x:Name="btnOrder" Command="{Binding PlaceOrderCommand}" Width="120" Content="下单"></Button>
</StackPanel>
</Grid>
</Border>
</Window>
using RestaurantOrderSystem.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace RestaurantOrderSystem.Views
{
/// <summary>
/// OrderView.xaml 的交互逻辑
/// </summary>
public partial class OrderView : Window
{
public OrderView()
{
InitializeComponent();
this.DataContext = new OrderViewModel();
}
}
}
App.cs
<Application x:Class="RestaurantOrderSystem.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RestaurantOrderSystem"
StartupUri="Views/OrderView.xaml">
<Application.Resources>
</Application.Resources>
</Application>
git地址👇
https://github.com/wanghuayu-hub2021/OrderSystem.git
许个愿,这周有个offer。