9. 商品下单
9.1 页面布局
页面布局仿照京东商品布局,在ItemControl控件内分为3行,分别是图片,标题,价格和加购物车按钮
数据库Product表新增列Title,类型为nvarchar(50) 。
在Button.xaml中新增加入购物车样式OrderButtonStyle
< Style x: Key= " OrderButtonStyle" TargetType = " Button" >
<Setter Property="Height" Value="30" />
<Setter Property="Width" Value="80" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="#196BA3" />
<Setter Property="Background" Value="#FDB706" />
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate TargetType="Button" >
<Border Background=" { TemplateBinding Background} "
Height=" { TemplateBinding Height} "
Width=" { TemplateBinding Width} "
BorderBrush="Transparent"
BorderThickness="1"
CornerRadius="15" >
<TextBlock x : Name="textblock"
Text=" { TemplateBinding Content} "
Foreground=" { TemplateBinding Foreground} "
FontSize=" { TemplateBinding FontSize} "
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="5" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Background" Value="#2383FC" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</ Style>
在商品管理界面为增加和修改功能增加Title属性,如苹果添加的标题为 越南进口苹果3个装 标准果 500-550g 。
将ItemControl的布局方式设置为瀑布流WrapPanel。
设置选中后的改变样式,鼠标移入显示商品框。
< UserControl x: Class= " 超市管理系统.View.OrderView"
xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns: x= " http://schemas.microsoft.com/winfx/2006/xaml"
xmlns: mc= " http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns: d= " http://schemas.microsoft.com/expression/blend/2008"
xmlns: local= " clr-namespace:超市管理系统.View" xmlns: i= " http://schemas.microsoft.com/expression/2010/interactivity"
mc: Ignorable= " d"
Background = " {Binding AppData.Background}"
DataContext = " {Binding Source={StaticResource Locator}, Path=OrderViewModel}"
d: DesignHeight= " 450" d: DesignWidth= " 800" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Loaded" >
< i: InvokeCommandAction Command = " {Binding LoadedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
< Grid>
< Grid.RowDefinitions>
< RowDefinition Height = " 40" />
< RowDefinition/>
</ Grid.RowDefinitions>
< Border BorderBrush = " #22304B" BorderThickness = " 0 0 0 1" >
< TextBlock Text = " 商品下单" VerticalAlignment = " center" Margin = " 5 0 0 0" Foreground = " {Binding AppData.Foreground}" FontSize = " 16" />
</ Border>
< Grid Grid.Row = " 1" >
< ItemsControl ItemsSource = " {Binding ProductList}" d: ItemsSource= " {Binding ProductList}" >
< ItemsControl.ItemsPanel>
< ItemsPanelTemplate>
< WrapPanel/>
</ ItemsPanelTemplate>
</ ItemsControl.ItemsPanel>
< ItemsControl.ItemTemplate>
< DataTemplate>
< Grid Width = " 150" Height = " 200" Margin = " 5" >
< Grid.Style>
< Style TargetType = " Grid" >
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Background" Value="#384560" />
</Trigger>
</Style.Triggers>
</ Style>
</ Grid.Style>
< Grid.RowDefinitions>
< RowDefinition/>
< RowDefinition Height = " auto" />
< RowDefinition Height = " auto" />
</ Grid.RowDefinitions>
< Image Source = " {Binding BitmapImage}" ToolTip = " Name" Stretch = " Uniform" />
< TextBlock Grid.Row = " 1" Text = " {Binding Title}" FontSize = " 16" TextWrapping = " Wrap" Margin = " 5 0 5 0" />
< TextBlock Grid.Row = " 2" Text = " {Binding Price, StringFormat={}{0:C2}}" FontSize = " 16" HorizontalAlignment = " Left" VerticalAlignment = " Center" Foreground = " Red" Margin = " 5 5 5 5" />
< Button Grid.Row = " 2" Content = " 加入购物车" Style = " { DynamicResource OrderButtonStyle} " HorizontalAlignment = " Right" Width = " 80" BorderThickness = " 1" Margin = " 5 5 5 5" />
</ Grid>
</ DataTemplate>
</ ItemsControl.ItemTemplate>
</ ItemsControl>
</ Grid>
</ Grid>
</ UserControl>
实现效果如下图:
9.2 顾客登录
由于原设计人员表分为了Customer表和Member表,此处需要在数据库中为Customer表人员增加Password列,默认设置密码为1。在Visual Studio中更新Customer表。
修改登录页面,在密码下新增顾客类别。在Appdata中新增属性public Customer CurrentCustomer { get; set; } = new Customer();
在Entity→Model中新增CurrentUserType
namespace 超市管理系统. Entity. Model
{
public enum CurrentUserType
{
管理员,
顾客
}
}
为在Debug模式下免除输入密码和用户名的繁琐,此处采用# if debug # end if模式来实现输入用户命和密码仅在if debug下,当程序release时,该区域代码不生效。
为实现TextBox绑定内容随radiobutton的选择而改变,此处采用扩展方式,扩展属性NameEx和PasswordEx。在界面加载时默认为admin。
namespace 超市管理系统. Entity
{
public partial class Member : BaseModel
{
public string NameEx
{
get
{
return Name;
}
set
{
Name = value ;
RaisePropertyChanged ( ) ;
}
}
public string PasswordEx
{
get
{
return Password;
}
set
{
Password = value ;
RaisePropertyChanged ( ) ;
}
}
}
}
LoginView界面增加LoadedCommand触发器,和类别选择。修改了两个Textbox的绑定属性,实现界面代码如下:
< Window x: Class= " 超市管理系统.View.LoginView"
x: Name= " loginView"
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:超市管理系统.View" xmlns: i= " http://schemas.microsoft.com/expression/2010/interactivity"
mc: Ignorable= " d"
Background = " {Binding AppData.Background}"
WindowStartupLocation = " CenterScreen"
ResizeMode = " NoResize"
DataContext = " {Binding Source={StaticResource Locator}, Path=LoginViewModel}"
Title = " 系统登录" Height = " 400" Width = " 800" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Loaded" >
< i: InvokeCommandAction Command = " {Binding LoadedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
< Grid>
< Grid.RowDefinitions >
< RowDefinition Height = " 150" />
< RowDefinition/>
</ Grid.RowDefinitions>
< TextBlock Grid.Row = " 0" Text = " {Binding AppData.FullTitle}" VerticalAlignment = " Center" HorizontalAlignment = " Center" Foreground = " White" FontSize = " 30" >
< TextBlock.Effect>
< DropShadowEffect/>
</ TextBlock.Effect>
</ TextBlock>
< StackPanel Grid.Row = " 1" HorizontalAlignment = " Center" VerticalAlignment = " Top" >
< DockPanel>
< TextBlock Text = " 用户名:" Width = " 50" VerticalAlignment = " Center" Foreground = " {Binding AppData.Foreground}" />
< TextBox x: Name= " userNameTextBox" Text = " {Binding Member.NameEx, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment = " Center" Height = " 25" Width = " 130" />
</ DockPanel>
< DockPanel Margin = " 0 15 0 0" >
< TextBlock Text = " 密 码:" Width = " 50" VerticalAlignment = " Center" Foreground = " {Binding AppData.Foreground}" />
< TextBox x: Name= " passwordTextBox" Text = " {Binding Member.PasswordEx, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment = " Center" Height = " 25" Width = " 130" />
</ DockPanel>
< DockPanel Margin = " 0 15 0 0" >
< TextBlock Text = " 类 别:" Width = " 50" VerticalAlignment = " Center" Foreground = " {Binding AppData.Foreground}" />
< RadioButton x: Name= " adminRB" Content = " 管理员" Tag = " 管理员" Width = " 65" VerticalAlignment = " Center" Foreground = " {Binding AppData.Foreground}" IsChecked = " True" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Checked" >
< i: InvokeCommandAction Command = " {Binding CheckedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
</ RadioButton>
< RadioButton Content = " 顾客" Tag = " 顾客" Width = " 65" VerticalAlignment = " Center" Foreground = " {Binding AppData.Foreground}" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Checked" >
< i: InvokeCommandAction Command = " {Binding CheckedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
</ RadioButton>
</ DockPanel>
< StackPanel Orientation = " Horizontal" HorizontalAlignment = " Right" Margin = " 0 15 0 0" >
< Button x: Name= " dengLu" Command = " {Binding LoginCommand}"
CommandParameter = " {Binding ElementName=loginView}"
Content = " 登录" Width = " 60" Height = " 25" />
< Button x: Name= " tuiChu" Command = " {Binding ExitCommand}"
CommandParameter = " {Binding ElementName=loginView}"
Content = " 退出" Width = " 60" Height = " 25" Margin = " 30 0 0 0" />
</ StackPanel>
</ StackPanel>
</ Grid>
</ Window>
using GalaSoft. MvvmLight ;
using GalaSoft. MvvmLight. Command ;
using System ;
using System. Collections. Generic ;
using System. Linq ;
using System. Text ;
using System. Threading. Tasks ;
using System. Windows ;
using System. Windows. Controls ;
using 超市管理系统. Entity;
using 超市管理系统. Entity. Model;
using 超市管理系统. View;
namespace 超市管理系统. ViewModel
{
public class LoginViewModel : ViewModelBase2
{
public MemberProvider memberProvider = new MemberProvider ( ) ;
public CustomerProvider customerProvider = new CustomerProvider ( ) ;
private Member member = new Member ( ) ;
public Member Member
{
get { return member; }
set
{
member = value ;
RaisePropertyChanged ( ) ;
}
}
#region commands
public RelayCommand< Window> LoadedCommand
{
get
{
return new RelayCommand< Window> ( ( view) =>
{
#if DEBUG
Member. NameEx = "admin" ;
Member. PasswordEx = "123" ;
#endif
} ) ;
}
}
public RelayCommand< LoginView> LoginCommand
{
get
{
return new RelayCommand< LoginView> ( ( view) =>
{
if ( string . IsNullOrEmpty ( Member. NameEx) && string . IsNullOrEmpty ( Member. Password) )
{
return ;
}
if ( AppData. UserType == CurrentUserType. 管理员)
{
var list = memberProvider. GetAll ( ) ;
var model = list. FirstOrDefault ( t => t. Name == Member. NameEx && t. Password == Member. Password) ;
if ( model != null )
{
AppData. CurrentUser = model;
new MainWindow ( ) . Show ( ) ;
view. Close ( ) ;
}
else
{
MessageBox. Show ( "用户名或密码错误!" ) ;
}
}
else
{
var list = customerProvider. GetAll ( ) ;
var model = list. FirstOrDefault ( t => t. Name == Member. NameEx && t. Password == Member. Password) ;
if ( model != null )
{
AppData. CurrentCustomer = model;
new MainWindow ( ) . Show ( ) ;
view. Close ( ) ;
}
else
{
MessageBox. Show ( "用户名或密码错误!" ) ;
}
}
} ) ;
}
}
public RelayCommand< LoginView> ExitCommand
{
get
{
return new RelayCommand< LoginView> ( ( view) =>
{
view. Close ( ) ;
} ) ;
}
set ;
}
public RelayCommand< RadioButton> CheckedCommand
{
get
{
return new RelayCommand< RadioButton> ( ( button) =>
{
if ( button == null ) { return ; }
if ( button is RadioButton radioButton)
{
if ( radioButton. Tag == null )
{
return ;
}
if ( Enum. TryParse ( radioButton. Tag. ToString ( ) , false , out CurrentUserType result) )
{
AppData. UserType = result;
#if DEBUG
if ( result == CurrentUserType. 顾客)
{
Member. NameEx = "张三" ;
}
else
{
Member. NameEx = "admin" ;
}
#endif
}
}
} ) ;
}
set ;
}
#endregion
}
}
9.3 商品下单
新建CustomerWindow.xaml和CustomerWindowViewModel为顾客登录界面和功能实现。
顶部设计商品浏览、购物车 等按钮功能,复用radiobutton样式和写法。
数据库为Order表新增SN nvarchar(50) 、Paydate datetime 两个字段。
采用ContentControl控件,直接展示商品浏览界面。
全局变量设置当前订单购物车public Order CurrentOrder { get; set; } = null;
为Order建立部分类,扩展订单详情列表,用以加载购物车的订单详情,如下:
using GalaSoft. MvvmLight ;
using System. Collections. Generic ;
using 超市管理系统. Entity. Model;
namespace 超市管理系统. Entity
{
public partial class Order : BaseModel
{
private List< OrderDetail> children = new List< OrderDetail> ( ) ;
public List< OrderDetail> Children
{
get { return children ; }
set { children = value ; RaisePropertyChanged ( ) ; }
}
}
}
CustomerWindow.xaml实现代码如下:
< Window x: Class= " 超市管理系统.View.CustomerWindow"
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:超市管理系统.View"
xmlns: i= " http://schemas.microsoft.com/expression/2010/interactivity"
mc: Ignorable= " d"
Title = " 馒头超市管理系统" Height = " 800" Width = " 1200"
Background = " {Binding AppData.Background}"
WindowStartupLocation = " CenterScreen"
DataContext = " {Binding Source={StaticResource Locator}, Path=Main}" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Loaded" >
< i: InvokeCommandAction Command = " {Binding LoadedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
< Grid>
< Grid.RowDefinitions>
< RowDefinition Height = " 40" />
< RowDefinition/>
</ Grid.RowDefinitions>
< Grid Grid.Row = " 0" >
< Grid.ColumnDefinitions>
< ColumnDefinition/>
< ColumnDefinition/>
</ Grid.ColumnDefinitions>
< StackPanel Grid.Row = " 0" Grid.Column = " 0" Orientation = " Horizontal" VerticalAlignment = " Center" >
< RadioButton x: Name= " OrderView" Style = " { StaticResource MenuRadioButtonStyle} " VerticalAlignment = " Center" Content = " 商品下单" Tag = "  " Checked = " View_Checked" />
< RadioButton x: Name= " ShoppingCarView" Style = " { StaticResource MenuRadioButtonStyle} " VerticalAlignment = " Center" Content = " 购物车" Tag = "  " Checked = " View_Checked" />
< RadioButton x: Name= " CustomerOrderView" Style = " { StaticResource MenuRadioButtonStyle} " VerticalAlignment = " Center" Content = " 订单详情" Tag = "  " Checked = " View_Checked" />
</ StackPanel>
</ Grid>
< Grid Grid.Row = " 1" >
< ContentControl x: Name= " container" >
< local: OrderView/>
</ ContentControl>
</ Grid>
</ Grid>
</ Window>
CustomerWindow.xaml.cs实现代码如下:
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 超市管理系统. View
{
public partial class CustomerWindow : Window
{
public CustomerWindow ( )
{
InitializeComponent ( ) ;
}
private void View_Checked ( object sender, RoutedEventArgs e)
{
if ( sender is RadioButton radioButton)
{
if ( string . IsNullOrEmpty ( radioButton. Name) ) return ;
Type type = Type. GetType ( "超市管理系统.View." + radioButton. Name) ;
container. Content = Activator. CreateInstance ( type) ;
}
}
}
}
CustomerWindowViewModel实现了界面加载时查询购物车,购物车实现逻辑为:界面加载时查询该顾客Id,且状态未完成的Order。若存在,则加入购物车时为增加一条数据或修改有同样产品时的数量;若不存在,则创造一条数据。由于在界面加载时已查询购物车,因此在 点击加入购物车按钮时,可省略查询,直接查询购物车中是否有次物品,有则增加数量,无则新增一条数据 。
using GalaSoft. MvvmLight. Command ;
using System ;
using System. Collections. Generic ;
using System. Linq ;
using System. Text ;
using System. Threading. Tasks ;
using System. Windows ;
using System. Windows. Controls ;
using 超市管理系统. Entity;
using 超市管理系统. Entity. Model;
namespace 超市管理系统. ViewModel
{
public class OrderViewModel : ViewModelBase2
{
private OrderProvider orderProvider = new OrderProvider ( ) ;
private OrderDetailProvider orderDetailProvider = new OrderDetailProvider ( ) ;
private List< Product> productList = new List< Product> ( ) ;
public List< Product> ProductList
{
get { return productList; }
set
{
productList = value ;
RaisePropertyChanged ( ) ;
}
}
private Product selectedProduct;
public Product SelectedProduct
{
get { return selectedProduct; }
set
{
selectedProduct = value ;
RaisePropertyChanged ( ) ;
}
}
#region command
public RelayCommand< UserControl> LoadedCommand
{
get
{
return new RelayCommand< UserControl> ( ( view) =>
{
ProductList = ProductViewModel. productProvider. GetAll ( ) ;
var tmpOrder = orderProvider. GetAll ( ) . FirstOrDefault ( t => t. CustomerId == AppData. CurrentCustomer. Id && t. OrderState == OrderState. 未完成. ToString ( ) ) ;
if ( tmpOrder == null )
{
Order order = new Order ( ) ;
order. CustomerId = AppData. CurrentCustomer. Id;
order. OrderDate = DateTime. Now;
order. OrderState = OrderState. 未完成. ToString ( ) ;
order. SN = Guid. NewGuid ( ) . ToString ( ) ;
int count = orderProvider. Insert ( order) ;
if ( count > 0 )
{
AppData. CurrentOrder = order;
}
}
else
{
AppData. CurrentOrder = tmpOrder;
AppData. CurrentOrder. Children = orderDetailProvider. GetAll ( ) . Where ( t => t. OrderId == tmpOrder. Id) . ToList ( ) ;
}
} ) ;
}
}
public RelayCommand< Product> OrderCommand
{
get
{
return new RelayCommand< Product> ( ( product) =>
{
var tmpOrderDetail = AppData. CurrentOrder. Children. FirstOrDefault ( t => t. OrderId == AppData. CurrentOrder. Id && t. ProductId == product. Id) ;
int count;
if ( tmpOrderDetail == null )
{
OrderDetail orderDetail = new OrderDetail ( ) ;
orderDetail. ProductId = product. Id;
orderDetail. OrderId = AppData. CurrentOrder. Id;
orderDetail. InsertDate = DateTime. Now;
orderDetail. Price = product. Price;
orderDetail. Quantity = 1 ;
count = orderDetailProvider. Insert ( orderDetail) ;
AppData. CurrentOrder. Children. Add ( orderDetail) ;
}
else
{
tmpOrderDetail. Quantity += 1 ;
count = orderDetailProvider. Update ( tmpOrderDetail) ;
}
if ( count > 0 )
{
MessageBox. Show ( "加入购物车成功!" ) ;
}
} ) ;
}
}
#endregion
}
}
9.4 购物车详情与结算
购物车界面主体分为两行,第一行为详情,第二行为合计金额与支付按钮
第一行分为三列,第一列为图片,第二列为标题与价格,第三列数量的显示与加减按钮、移除购物车按钮。
购物车需实现增加、减少、库存同步更新、移除购物车、结算等命令。界面如下:
< UserControl x: Class= " 超市管理系统.View.ShoppingCarView"
xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns: x= " http://schemas.microsoft.com/winfx/2006/xaml"
xmlns: mc= " http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns: d= " http://schemas.microsoft.com/expression/blend/2008"
xmlns: local= " clr-namespace:超市管理系统.View"
xmlns: i= " http://schemas.microsoft.com/expression/2010/interactivity"
DataContext = " {Binding Source={StaticResource Locator}, Path=ShoppingCarViewModel}"
mc: Ignorable= " d"
Background = " {Binding AppData.Background}"
d: DesignHeight= " 450" d: DesignWidth= " 800" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Loaded" >
< i: InvokeCommandAction Command = " {Binding LoadedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
< Grid>
< Grid.RowDefinitions>
< RowDefinition/>
< RowDefinition Height = " 40" />
</ Grid.RowDefinitions>
< ScrollViewer>
< ItemsControl Grid.Row = " 0" ItemsSource = " {Binding AppData.CurrentOrder.Children}" >
< ItemsControl.ItemsPanel>
< ItemsPanelTemplate>
< StackPanel/>
</ ItemsPanelTemplate>
</ ItemsControl.ItemsPanel>
< ItemsControl.ItemTemplate>
< DataTemplate>
< Grid Height = " 150" Margin = " 5" >
< Grid.Style>
< Style TargetType = " Grid" >
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Background" Value="#384560" />
</Trigger>
</Style.Triggers>
</ Style>
</ Grid.Style>
< Grid.ColumnDefinitions>
< ColumnDefinition Width = " auto" />
< ColumnDefinition/>
< ColumnDefinition/>
</ Grid.ColumnDefinitions>
< Image Grid.Column = " 0" Source = " {Binding BitmapImage}" ToolTip = " Name" Stretch = " Fill" Width = " 150" HorizontalAlignment = " Left" />
< Grid Grid.Column = " 1" Grid.Row = " 1" Margin = " 20 0 0 0" >
< Grid.RowDefinitions>
< RowDefinition/>
< RowDefinition/>
</ Grid.RowDefinitions>
< TextBlock Grid.Row = " 0" Text = " {Binding ProductTitle}" Foreground = " White" HorizontalAlignment = " Left" VerticalAlignment = " Center" FontSize = " 16" TextWrapping = " Wrap" Margin = " 5 0 5 0" />
< TextBlock Grid.Row = " 1" Text = " {Binding Price, StringFormat={}{0:C2}}" FontSize = " 16" HorizontalAlignment = " Left" VerticalAlignment = " Center" Foreground = " Red" Margin = " 5 5 5 5" />
</ Grid>
< Grid Grid.Column = " 2" >
< Grid.ColumnDefinitions>
< ColumnDefinition/>
< ColumnDefinition/>
</ Grid.ColumnDefinitions>
< StackPanel Grid.Column = " 0" Orientation = " Horizontal" >
< Button Content = " +" Height = " 25" Width = " 50" Margin = " 5"
Command = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}, Path=DataContext.AddCommand}"
CommandParameter = " {Binding .}" />
< TextBox Text = " {Binding QuantityEx, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment = " Center" VerticalContentAlignment = " Center" Height = " 25" Width = " 50" />
< Button Content = " -" Height = " 25" Width = " 50" Margin = " 5"
Command = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}, Path=DataContext.DecCommand}"
CommandParameter = " {Binding .}" />
</ StackPanel>
< Button Grid.Column = " 1" Content = " 移出购物车" Height = " 25" Width = " auto" Margin = " 5"
Command = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}, Path=DataContext.RemoveCommand}"
CommandParameter = " {Binding .}" />
</ Grid>
</ Grid>
</ DataTemplate>
</ ItemsControl.ItemTemplate>
</ ItemsControl>
</ ScrollViewer>
< StackPanel Grid.Row = " 1" Orientation = " Horizontal" HorizontalAlignment = " Right" >
< TextBlock Text = " 合计:" VerticalAlignment = " Center" FontSize = " 16" Foreground = " White" Margin = " 5" />
< TextBlock Text = " {Binding SumPrice}" VerticalAlignment = " Center" FontSize = " 16" Foreground = " White" Margin = " 5" />
< Button Content = " 结算" Style = " { DynamicResource OrderButtonStyle} "
Command = " {Binding PayCommand}"
HorizontalAlignment = " Right" Width = " 80" BorderThickness = " 1" Margin = " 5" />
</ StackPanel>
</ Grid>
</ UserControl>
ShoppingCarViewModel.cs 功能代码实现如下:
using GalaSoft. MvvmLight. Command ;
using System ;
using System. Collections. Generic ;
using System. Linq ;
using System. Text ;
using System. Threading. Tasks ;
using System. Windows ;
using System. Windows. Controls ;
using 超市管理系统. Entity;
using 超市管理系统. Entity. Model;
namespace 超市管理系统. ViewModel
{
public class ShoppingCarViewModel : ViewModelBase2
{
public double sumPrice;
public double SumPrice
{
get { return sumPrice; }
set
{
sumPrice = value ; RaisePropertyChanged ( ) ;
}
}
public RelayCommand< UserControl> LoadedCommand
{
get
{
return new RelayCommand< UserControl> ( ( view) =>
{
if ( AppData. CurrentOrder != null )
{ SumPrice = ( double ) AppData. CurrentOrder. Children. Sum ( x => x. Price * x. Quantity) ; }
else SumPrice = 0 ;
} ) ;
}
}
public RelayCommand< OrderDetail> AddCommand
{
get
{
return new RelayCommand< OrderDetail> ( ( orderDetail) =>
{
var product = ProductViewModel. productProvider. GetAll ( ) . FirstOrDefault ( t => t. Id == orderDetail. ProductId) ;
if ( product != null )
{
if ( product. Quantity <= orderDetail. QuantityEx)
{
MessageBox. Show ( "库存不足!" ) ;
return ;
}
}
orderDetail. QuantityEx += 1 ;
OrderDetailViewModel. orderDetailProvider. Update ( orderDetail) ;
SumPrice = ( double ) AppData. CurrentOrder. Children. Sum ( x => x. Price * x. Quantity) ;
} ) ;
}
}
public RelayCommand< OrderDetail> DecCommand
{
get
{
return new RelayCommand< OrderDetail> ( ( orderDetail) =>
{
if ( orderDetail. QuantityEx == 1 ) return ;
orderDetail. QuantityEx -= 1 ;
OrderDetailViewModel. orderDetailProvider. Update ( orderDetail) ;
SumPrice = ( double ) AppData. CurrentOrder. Children. Sum ( x => x. Price * x. Quantity) ;
} ) ;
}
}
public RelayCommand< OrderDetail> RemoveCommand
{
get
{
return new RelayCommand< OrderDetail> ( ( orderDetail) =>
{
AppData. CurrentOrder. Children. Remove ( orderDetail) ;
OrderDetailViewModel. orderDetailProvider. Delete ( orderDetail) ;
SumPrice = ( double ) AppData. CurrentOrder. Children. Sum ( x => x. Price * x. Quantity) ;
} ) ;
}
}
public RelayCommand PayCommand
{
get
{
return new RelayCommand ( ( ) =>
{
if ( AppData. CurrentOrder. Children. Count == 0 )
{
MessageBox. Show ( "请加入购物车!" ) ;
return ;
}
int count = 0 ;
foreach ( var item in AppData. CurrentOrder. Children)
{
StockRecord stock = new StockRecord ( ) ;
stock. ProductId = item. ProductId;
stock. Type = StockType. 出库. ToString ( ) ;
stock. StockDate = DateTime. Now;
stock. Quantity = item. Quantity;
count += InstorageViewModel. stockRecordProvider. Insert ( stock) ;
var product = ProductViewModel. productProvider. GetAll ( ) . FirstOrDefault ( t => t. Id == item. ProductId) ;
if ( product != null )
{
product. Quantity -= item. Quantity;
ProductViewModel. productProvider. Update ( product) ;
}
}
AppData. CurrentOrder. PayDate = DateTime. Now;
AppData. CurrentOrder. OrderState = OrderState. 已完成. ToString ( ) ;
count += OrderViewModel. orderProvider. Update ( AppData. CurrentOrder) ;
if ( count == AppData. CurrentOrder. Children. Count + 1 )
{
MessageBox. Show ( "购物成功!" ) ;
AppData. CurrentOrder. Children. Clear ( ) ;
AppData. CurrentOrder = null ;
return ;
}
} ) ;
}
}
}
}
9.5 订单详情管理
run 可以实现textblock同一行字不同的样式
为Order类增加总金额属性SumPrice.
新建顾客订单详情页CustomerOrderView.xaml,绑定订单list,表头分为四个部分,分别为order类的SN、状态、date和SumPrice
< UserControl x: Class= " 超市管理系统.View.CustomerOrderView"
xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns: x= " http://schemas.microsoft.com/winfx/2006/xaml"
xmlns: mc= " http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns: d= " http://schemas.microsoft.com/expression/blend/2008"
xmlns: local= " clr-namespace:超市管理系统.View"
xmlns: i= " http://schemas.microsoft.com/expression/2010/interactivity"
mc: Ignorable= " d"
Background = " {Binding AppData.Background}"
DataContext = " {Binding Source={StaticResource Locator}, Path=CustomerOrderViewModel}"
d: DesignHeight= " 450" d: DesignWidth= " 800" >
< i: Interaction.Triggers>
< i: EventTrigger EventName = " Loaded" >
< i: InvokeCommandAction Command = " {Binding LoadedCommand}" CommandParameter = " {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</ i: EventTrigger>
</ i: Interaction.Triggers>
< Grid>
< ScrollViewer>
< ItemsControl ItemsSource = " {Binding OrderList}" >
< ItemsControl.ItemsPanel>
< ItemsPanelTemplate>
< StackPanel/>
</ ItemsPanelTemplate>
</ ItemsControl.ItemsPanel>
< ItemsControl.ItemTemplate>
< DataTemplate>
< Border BorderBrush = " #505B70" BorderThickness = " 1" Margin = " 10" >
< Grid >
< Grid.RowDefinitions>
< RowDefinition />
< RowDefinition/>
</ Grid.RowDefinitions>
< Border Grid.Row = " 0" Height = " 30" Background = " #505B70" >
< Grid>
< Grid.ColumnDefinitions>
< ColumnDefinition/>
< ColumnDefinition/>
< ColumnDefinition/>
< ColumnDefinition Width = " 100" />
</ Grid.ColumnDefinitions>
< TextBlock Grid.Column = " 0" HorizontalAlignment = " Left" VerticalAlignment = " Center" >
< Run Text = " 订单号:" />
< Run Text = " {Binding SN}" Foreground = " White" />
</ TextBlock>
< TextBlock Grid.Column = " 1" HorizontalAlignment = " Left" VerticalAlignment = " Center" >
< Run Text = " 状态:" />
< Run Text = " {Binding OrderState}" Foreground = " White" />
</ TextBlock>
< TextBlock Grid.Column = " 2" HorizontalAlignment = " Left" VerticalAlignment = " Center" >
< Run Text = " 支付时间:" />
< Run Text = " {Binding PayDate}" Foreground = " White" />
</ TextBlock>
< TextBlock Grid.Column = " 3" HorizontalAlignment = " Left" VerticalAlignment = " Center" >
< Run Text = " 总金额:" />
< Run Text = " {Binding SumPrice }" Foreground = " White" />
</ TextBlock>
</ Grid>
</ Border>
< Border Grid.Row = " 1" >
< DataGrid ItemsSource = " {Binding Children}" Style = " { StaticResource DataGridStyle} " >
< DataGrid.Columns>
< DataGridTemplateColumn Width = " auto" Header = " 商品名称" >
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< Grid>
< TextBox Text = " {Binding ProductTitle, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Style = " { StaticResource DataGridTextBoxStyle} " />
</ Grid>
</ DataTemplate>
</ DataGridTemplateColumn.CellTemplate>
</ DataGridTemplateColumn>
< DataGridTemplateColumn Width = " auto" Header = " 商品图片" >
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< Grid>
< Image Source = " {Binding BitmapImage}" >
< Image.ToolTip>
< Grid>
< Image Source = " {Binding BitmapImage}" />
</ Grid>
</ Image.ToolTip>
</ Image>
</ Grid>
</ DataTemplate>
</ DataGridTemplateColumn.CellTemplate>
</ DataGridTemplateColumn>
< DataGridTemplateColumn Width = " auto" Header = " 单价" >
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< Grid>
< TextBox Text = " {Binding Price, Mode=OneWay, UpdateSourceTrigger=LostFocus}" Style = " { StaticResource DataGridTextBoxStyle} " HorizontalAlignment = " Left" />
</ Grid>
</ DataTemplate>
</ DataGridTemplateColumn.CellTemplate>
</ DataGridTemplateColumn>
< DataGridTemplateColumn Width = " auto" Header = " 数量" >
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< Grid>
< TextBox Text = " {Binding QuantityEx, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Style = " { StaticResource DataGridTextBoxStyle} " HorizontalAlignment = " Left" />
</ Grid>
</ DataTemplate>
</ DataGridTemplateColumn.CellTemplate>
</ DataGridTemplateColumn>
< DataGridTemplateColumn Width = " auto" Header = " 日期" >
< DataGridTemplateColumn.CellTemplate>
< DataTemplate>
< Grid>
< TextBox Text = " {Binding InsertDate, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Style = " { StaticResource DataGridTextBoxStyle} " HorizontalAlignment = " Left" />
</ Grid>
</ DataTemplate>
</ DataGridTemplateColumn.CellTemplate>
</ DataGridTemplateColumn>
</ DataGrid.Columns>
</ DataGrid>
</ Border>
</ Grid>
</ Border>
</ DataTemplate>
</ ItemsControl.ItemTemplate>
</ ItemsControl>
</ ScrollViewer>
</ Grid>
</ UserControl>
在CustomerOrderViewModel实现,界面加载订单详情内容
using GalaSoft. MvvmLight. Command ;
using System ;
using System. Collections. Generic ;
using System. Collections. ObjectModel ;
using System. Linq ;
using System. Text ;
using System. Threading. Tasks ;
using System. Windows. Controls ;
using 超市管理系统. Entity;
using 超市管理系统. Entity. Model;
namespace 超市管理系统. ViewModel
{
public class CustomerOrderViewModel : ViewModelBase2
{
private ObservableCollection< Order> orders = new ObservableCollection< Order> ( ) ;
public ObservableCollection< Order> OrderList
{
get { return orders; }
set { orders = value ; RaisePropertyChanged ( ) ; }
}
public RelayCommand< UserControl> LoadedCommand
{
get
{
return new RelayCommand< UserControl> ( ( view) =>
{
var _orders = OrderViewModel. orderProvider. GetAll ( ) . Where ( t => t. CustomerId == AppData. CurrentCustomer. Id && t. OrderState == OrderState. 已完成. ToString ( ) ) ;
if ( _orders != null )
{
OrderList. Clear ( ) ;
foreach ( var order in _orders)
{
OrderList. Add ( order) ;
var details = OrderDetailViewModel. orderDetailProvider. GetAll ( ) . Where ( t => t. OrderId == order. Id ) ;
if ( details != null )
{
order. Children. Clear ( ) ;
foreach ( var detail in details)
{
order. Children. Add ( detail) ;
order. SumPrice += ( double ) ( detail. Price * detail. QuantityEx) ;
}
}
}
}
} ) ;
}
}
}
}