项目创建
[一、 项目创建](#一、 项目创建)
[1. 数据库设置](#1. 数据库设置)
[2. 数据库连接](#2. 数据库连接)
[3. 构造供货商Provider](#3. 构造供货商Provider)
[二、 登录窗口](#二、 登录窗口)
[1. 窗口设置](#1. 窗口设置)
[2. 优化登录页面布局](#2. 优化登录页面布局)
[三、 系统开发](#三、 系统开发)
1.菜单设计
[2. 界面切换](#2. 界面切换)
[3. 顾客相关功能](#3. 顾客相关功能)
一、 项目创建
1. 数据库设置
建立ShoppingDB数据库,采用默认设置,建立Member表,字段为Id(主键int)、Name(nvarchar50)、Password(nvarchar50)、Level(nvarchar50)、InsertDate(datetime)
Id字段设置为是标识 ,标识增量为1
数据库建立其他表与表结构如下
2. 数据库连接
在VS界面建立Entity(截图为DAL)文件夹,并添加ADO.NET实体,命名为ShoppingModel
选择来自数据库的EF设计器
新建连接,MicroSoft SQL Server。有可能提示缺少文件,点击下一步确定安装。
服务器名称检索不到的话可以直接输入. ,代表本地服务器。数据库名称可检索到刚建立的ShoppingDB
勾选是
勾选表,点击完成
3. 构造供货商Provider
c#创建接口IProvider
设置接口IProvider为泛型,限制泛型为class
建立数据库的增删改查函数
Entity增加ProvideBase类,设置为abstract类
Entity增加MemberProvide类,继承自ProviderBase与IProvider,IProvider泛型为Member,实现接口
在ProviderBase类中定义字段 public ShoppingDBEntities db = new ShoppingDBEntities();
修改MemberProvider类,建立增删改查代码如下
csharp
复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 超市管理系统.Entity
{
public class MemberProvider : ProviderBase, Iprovider<Member>
{
public int Delete(Member entity)
{
db.Entry(entity).State =System.Data.Entity.EntityState.Deleted;
return db.SaveChanges();
}
public List<Member> GetAll()
{
return db.Member.ToList();
}
public int Insert(Member entity)
{
db.Entry(entity).State = System.Data.Entity.EntityState.Added;
return db.SaveChanges();
}
public int Update(Member entity)
{
db.Entry(entity).State = System.Data.Entity.EntityState.Modified;
return db.SaveChanges();
}
}
}
Entity增加ProductProvider类,继承自ProviderBase与IProvider,IProvider泛型为Product
修改MemberProvider类,建立增删改查代码如下
csharp
复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 超市管理系统.Entity
{
public class ProductProvider : ProviderBase, Iprovider<Product>
{
ProductProviderpublic int Delete(Product entity)
{
db.Entry(entity).State = System.Data.Entity.EntityState.Deleted;
return db.SaveChanges();
}
public List<Product > GetAll()
{
return db.Product.ToList();
}
public int Insert(Product entity)
{
db.Entry(entity).State = System.Data.Entity.EntityState.Added;
return db.SaveChanges();
}
public int Update(Product entity)
{
db.Entry(entity).State = System.Data.Entity.EntityState.Modified;
return db.SaveChanges();
}
}
}
数据库其他表继承自ProviderBase与IProvider建立*****Provider对应的类,并增加增删改查代码。
二、 登录窗口
1. 窗口设置
数据库内Member表,点击编辑前200行 可在界面增加内容,此处增加1,admin,123,9,null
VS界面创建View文件夹,创建LoginView窗体,在ViewModel文件夹内创建LoginViewModel类,并继承ViewModelBase,ViewModelBase已实现消息通知
改造 ViewModelLocator类,在原内容基础上仿照MainViewModel的写法增加以下
csharp
复制代码
public class ViewModelLocator
{
public ViewModelLocator()
{
SimpleIoc.Default.Register<LoginViewModel>();
}
public LoginViewModel LoginViewModel
{
get
{
return ServiceLocator.Current.GetInstance<LoginViewModel>();
}
}
}
LoginView.xaml内增加数据上下文来源 DataContext="{Binding Source={StaticResource Locator}, Path=LoginViewModel}"
在app.xaml中修改启动窗口为登录窗口 StartupUri="View/LoginView.xaml"
在根目录下创建类AppData.cs,并继承ObservableObject ,使用懒汉Lazy模式,创造唯一实例
AppData.cs创建属性 public Member CurrentUser { get; set; } = new Member();
csharp
复制代码
public class AppData: ObservableObject
{
public static AppData Instance{ get; set; } = new Lazy<AppData>(() => new AppData()).Value;
public Member CurrentUser { get; set; } = new Member();
}
LoginViewModel.cs内创建的当前用户实体为只读属性 public AppData AppData => AppData.Instance;"
创建Member类的用户实体字段和属性
csharp
复制代码
//默认放入账号和密码,用于调试
private Member member = new Member() { Name = "admin", Password="123"};
public Member Member
{
get { return member; }
set
{
member = value;
RaisePropertyChanged();
}
}
创建登录按钮和退出按钮的命令
LoginView.xaml界面的window命名loginView,按钮绑定命令使ElementName = loginView
csharp
复制代码
#region commands
public RelayCommand<LoginView> LoginCommand
{
get
{
return new RelayCommand<LoginView>((view) =>
{
if(string.IsNullOrEmpty(member.Name)&& string.IsNullOrEmpty(member.Password))
{
return;
}
var list = memberProvider.GetAll();
var model = list.FirstOrDefault(t => t.Name == member.Name && t.Password == member.Password);
if (model != null)
{
AppData.CurrentUser = model;
}
else
{
MessageBox.Show("用户名或密码错误!");
new MainWindow().Show();
}
});
}
}
public RelayCommand<LoginView> ExitCommand
{
get
{
return new RelayCommand<LoginView>((view) =>
{
view.Close();
//终止进程,退出当前代码
//Environment.Exit(0);
});
}
set;
}
#endregion
xml
复制代码
<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"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
DataContext="{Binding Source={StaticResource Locator}, Path=LoginViewModel}"
Title="系统登录" Height="250" Width="450">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" >
<DockPanel>
<TextBlock Text="用户名:" Width="50" VerticalAlignment="Center" Height="25"/>
<TextBox x:Name="userNameTextBox" Text="{Binding Member.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100"/>
</DockPanel>
<DockPanel Margin="0 15 0 0">
<TextBlock Text="密 码:" Width="50" VerticalAlignment="Center" Height="25"/>
<TextBox x:Name="passwordTextBox" Text="{Binding Member.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100"/>
</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>
</Window>
由于在MvvmLight中已存在ViewModelBase,在ViewModel文件夹创建ViewModelBase2.cs ,继承ViewModelBase
因MainView需显示当前登录用户,需重新在MainViewModel内同样写 public AppData AppData => AppData.Instance;" ,因此作出修改LoginViewModel和MainViewModel重新继承自ViewModelBase2 ,将 public AppData AppData => AppData.Instance;" 放在ViewModelBase2内,LoginViewModel删去该行代码,MainViewModel也不需要再写该行代码。
2. 优化登录页面布局
使用Colors Lite 抓取素材颜色数值,作为背景色。
在AppData类内添加全局变量内容:系统名称、背景色、前景色。
csharp
复制代码
public Member CurrentUser { get; set; } = new Member();
/// <summary>
/// 超市名称
/// </summary>
public string Title => "馒头超市管理系统";
/// <summary>
/// 背景颜色
/// </summary>
public SolidColorBrush Background => new SolidColorBrush(Color.FromRgb(40, 53, 81));
/// <summary>
/// 前景颜色
/// </summary>
public SolidColorBrush Forgeround => new SolidColorBrush(Colors.White);
LoginView.xaml界面的window.title、TextBlock的背景色并使用Effect、前景色都改为Bingding
xml
复制代码
<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"
mc:Ignorable="d"
Background="{Binding AppData.Background}"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
DataContext="{Binding Source={StaticResource Locator}, Path=LoginViewModel}"
Title="系统登录" Height="400" Width="800">
<Grid>
<Grid.RowDefinitions >
<RowDefinition Height="150"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding AppData.Title}" 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.Forgeround}" Height="25"/>
<TextBox x:Name="userNameTextBox" Text="{Binding Member.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100"/>
</DockPanel>
<DockPanel Margin="0 15 0 0">
<TextBlock Text="密 码:" Width="50" VerticalAlignment="Center" Foreground="White" Height="25"/>
<TextBox x:Name="passwordTextBox" Text="{Binding Member.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100"/>
</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>
三、 系统开发
1.菜单设计
xml
复制代码
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="MenuRadioButtonStyle" TargetType="RadioButton">
<Setter Property="Foreground" Value="#eeefff"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<!--此时已将radio的模板形状设置为了border,将border的背景色绑定radiobutton背景色,触发器才会生效-->
<Border Background="{TemplateBinding Background}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{TemplateBinding Tag}" FontFamily="/Fonts/#FontAwesome" Margin="5"/>
<TextBlock Grid.Column="1" Text="{TemplateBinding Content}" Margin="5"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!--触发器的目标是radiobutton的背景色-->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="red"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<!--透明色-->
<Setter Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="Goldenrod"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
xml
复制代码
<Window x:Class="超市管理系统.MainWindow"
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:超市管理系统" xmlns:view="clr-namespace:超市管理系统.View"
mc:Ignorable="d"
Title="馒头超市管理系统" Height="800" Width="1200"
Background="{Binding AppData.Background}"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="1"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--左侧内容-->
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="" FontFamily="/Fonts/#FontAwesome" Margin="10" FontSize="30">
<TextBlock.Foreground>
<LinearGradientBrush>
<!--开始为蓝色 -->
<GradientStop Offset="0" Color="#C2F486" />
<!--结尾是红色 -->
<GradientStop Offset="1" Color="Red" />
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<TextBlock Text="{Binding AppData.Title}" Margin="0" Foreground="White" FontSize="20" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Grid.Row="1">
<RadioButton x:Name="IndexView" Style="{StaticResource MenuRadioButtonStyle}" Content="首页" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="OrderView" Style="{StaticResource MenuRadioButtonStyle}" Content="商品下单" Tag="" Checked="View_Checked"/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="商品管理" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="顾客管理" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="供应商管理" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="出库管理" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="入库管理" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="订单详情" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="用户管理" Tag=""/>
<RadioButton Style="{StaticResource MenuRadioButtonStyle}" Content="系统设置" Tag=""/>
</StackPanel>
</Grid>
<Border Grid.Column="1" Background="#22304B"/>
<!--右侧内容-->
<ContentControl Grid.Column="2" x:Name="container" >
<view:IndexView/>
</ContentControl>
</Grid>
<!--底部状态栏-->
<StatusBar Grid.Row="1">
<StatusBarItem>
<TextBlock Text="当前用户:" />
</StatusBarItem>
<StatusBarItem>
<TextBlock Text="{Binding AppData.CurrentUser.Name}" />
</StatusBarItem>
</StatusBar>
</Grid>
</Window>
2. 界面切换
在View文件夹创建UserControl用户控件IndexView.xaml代表首页界面,ViewModel文件夹创建IndexViewModel.cs,在ViewModelLocator中按格式添加IndexViewModel
采用相同的方法依次为每个菜单按钮完成上述操作
csharp
复制代码
using CommonServiceLocator;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using 超市管理系统.ViewModel;
namespace 超市管理系统.ViewModel
{
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<LoginViewModel>();
SimpleIoc.Default.Register<IndexViewModel>();
SimpleIoc.Default.Register<OrderViewModel>();
SimpleIoc.Default.Register<CustomerViewModel>();
SimpleIoc.Default.Register<GoodsViewModel>();
SimpleIoc.Default.Register<InstorageViewModel>();
SimpleIoc.Default.Register<OutstorageViewModel>();
SimpleIoc.Default.Register<OrderDetailViewModel>();
SimpleIoc.Default.Register<SettingViewModel>();
SimpleIoc.Default.Register<MemberViewModel>();
SimpleIoc.Default.Register<SupplierViewModel>();
}
/// <summary>
/// 主窗口所用
/// </summary>
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
/// <summary>
/// 登录窗口所用
/// </summary>
public LoginViewModel LoginViewModel
{
get
{
return ServiceLocator.Current.GetInstance<LoginViewModel>();
}
}
///lambda
public IndexViewModel IndexViewModel => ServiceLocator.Current.GetInstance<IndexViewModel>();
public OrderViewModel OrderViewModel => ServiceLocator.Current.GetInstance<OrderViewModel>();
public CustomerViewModel CustomerViewModel => ServiceLocator.Current.GetInstance<CustomerViewModel>();
public GoodsViewModel GoodsViewModel => ServiceLocator.Current.GetInstance<GoodsViewModel>();
public InstorageViewModel InstorageViewModel => ServiceLocator.Current.GetInstance<InstorageViewModel>();
public OutstorageViewModel OutstorageViewModel => ServiceLocator.Current.GetInstance<OutstorageViewModel>();
public OrderDetailViewModel OrderDetailViewModel => ServiceLocator.Current.GetInstance<OrderDetailViewModel>();
public SettingViewModel SettingViewModel => ServiceLocator.Current.GetInstance<SettingViewModel>();
public MemberViewModel MemberViewModel => ServiceLocator.Current.GetInstance<MemberViewModel>();
public SupplierViewModel SupplierViewModel => ServiceLocator.Current.GetInstance<SupplierViewModel>();
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
}
更新MemberView.xaml文件中的菜单Style、Name和Checked。
xml
复制代码
<StackPanel Grid.Row="1">
<RadioButton x:Name="IndexView" Style="{StaticResource MenuRadioButtonStyle}" Content="首页" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="OrderView" Style="{StaticResource MenuRadioButtonStyle}" Content="商品下单" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="GoodsView" Style="{StaticResource MenuRadioButtonStyle}" Content="商品管理" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="CustomerView" Style="{StaticResource MenuRadioButtonStyle}" Content="顾客管理" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="SupplierView" Style="{StaticResource MenuRadioButtonStyle}" Content="供应商管理" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="InstorageView" Style="{StaticResource MenuRadioButtonStyle}" Content="入库管理" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="OutstorageView" Style="{StaticResource MenuRadioButtonStyle}" Content="出库管理" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="OrderDetailView" Style="{StaticResource MenuRadioButtonStyle}" Content="订单详情" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="MemberView" Style="{StaticResource MenuRadioButtonStyle}" Content="用户管理" Tag="" Checked="View_Checked"/>
<RadioButton x:Name="SettingView" Style="{StaticResource MenuRadioButtonStyle}" Content="系统设置" Tag="" Checked="View_Checked"/>
</StackPanel>
通过Switch和反射的方法都可以实现点击进行切换
csharp
复制代码
using System.Windows;
using System.Windows.Controls;
using 超市管理系统.View;
namespace 超市管理系统
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void View_Checked(object sender, RoutedEventArgs e)
{
//页面切换
//if()等同于如果 sender is RadioButton,
//然后RadioButton radioButton = (RadioButton)sender;
if (sender is RadioButton radioButton)
{
if (string.IsNullOrEmpty(radioButton.Name)) return;
//第一种方法 通过switch进行导航
//switch (radioButton.Name)
//{
// case "IndexView":
// container.Content = new IndexView();
// break;
// case "OrderView":
// container.Content = new OrderView();
// break;
// case "CustomerView":
// container.Content = new CustomerView();
// break;
// case "GoodsView":
// container.Content = new GoodsView();
// break;
// case "InstorageView":
// container.Content = new InstorageView();
// break;
// case "MemberView":
// container.Content = new MemberView();
// break;
// case "OrderDetailView":
// container.Content = new OrderDetailView();
// break;
// case "OutstorageView":
// container.Content = new OutstorageView();
// break;
// case "SettingView":
// container.Content = new SettingView();
// break;
// case "SupplierView":
// container.Content = new SupplierView();
// break;
//第二种方法 通过反射进行导航
Type type = Type.GetType("超市管理系统.View." + radioButton.Name);
container.Content = Activator.CreateInstance(type);
}
}
}
}
}
3. 顾客相关功能