WPF学习——基于Mvvm模式下的餐馆订餐系统小示例

 

订餐小系统的界面主要内容为餐馆信息显示,菜品表格呈现。选择栏中按钮进行菜品的选择,可以对数量进行加减,并将订单信息实时显示在预购清单中。最后点击下单按钮,将订单信息保存到硬盘orders.txt文本中。界面呈现画面如下图所示。

  1. 数据库信息,我用的SQLServer。表格如下图所示。                                                                                      
  2. 新建Models文件夹,添加Dish与Restaurant类。
        class Dish
        {
            public int Id { get; set; }
            public string  Name { get; set; }
            public string Catagory { get; set; }
            public string  Comment { get; set; }
            public double Score { get; set; }
            public int Count { get; set; }
    
    
        }
        class Restaurant
        {
            public string Name { get; set; }
            public string Address { get; set; }
            public string PhoneNumber { get; set; }
    
        }

     

  3. 新增Db文件夹,添加localDb类。
      class localDb
        {
            public localDb()
            {
    
            }
            private List<Dish> Dishes;
            private List<Restaurant> Restaurants;
            public List<Dish> GetDishes()
            {
                Dishes = new List<Dish>();
                string connString = Properties.Settings.Default.Database;
                string sql = "SELECT  [Id],[Name],[Catagory],[Comment],[Score],[Count] FROM [test].[dbo].[Dish]";
                using (SqlConnection conn = new SqlConnection(connString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(sql, conn);
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Dish dish = new Dish() {Id=(int)reader["Id"], Name=(string)reader["Name"],Catagory=(string)reader["Catagory"],
                        Comment=(string)reader["Comment"],Score=(double)reader["Score"],Count=(int)reader["Count"]};
                        Dishes.Add(dish);
                    }
                    return Dishes;
                }
            }
            public List<Restaurant> GetRestaurants()
            {
                Restaurants = new List<Restaurant>();
                string connString = Properties.Settings.Default.Database;
                string sql = "SELECT TOP 1 [Name],[Address],[PhoneNumber] FROM [test].[dbo].[Restaurant]";
                using (SqlConnection conn = new SqlConnection(connString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(sql, conn);
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Restaurant restaurant = new Restaurant()
                        {
                            Name = (string)reader["Name"],
                            Address = (string)reader["Address"],
                            PhoneNumber = (string)reader["PhoneNumber"]
                        };
                        Restaurants.Add(restaurant);
                    }
                    return Restaurants;
                
                }
            }
            public string GetNameById(int? id)
            {
                localDb localDb = new localDb();
    
                string name = localDb.GetDishes().FirstOrDefault(t => t.Id == id).Name;
                return name;
            }
    
            public void CountAddOne(int? id)
            {
                string connString = Properties.Settings.Default.Database;
                string sql = "update test.dbo.Dish set [Count]=@count where Id=@id";
                localDb localDb = new localDb();
                List<Dish> dishes = localDb.GetDishes();
                var count = dishes.FirstOrDefault(t => t.Id == id).Count+1;
                using (SqlConnection conn=new SqlConnection(connString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(sql, conn);
                    cmd.Parameters.Add(new SqlParameter("@count",count));
                    cmd.Parameters.Add(new SqlParameter("@id",id));
                    cmd.ExecuteNonQuery();
                }
    
            }
    
            public void CountSubOne(int? id)
            {
                string connString = Properties.Settings.Default.Database;
                string sql = "update test.dbo.Dish set [Count]=@count where Id=@id";
                localDb localDb = new localDb();
                List<Dish> dishes = localDb.GetDishes();
                var count = dishes.FirstOrDefault(t => t.Id == id).Count - 1;
                if (count >= 0)
                {
                    using (SqlConnection conn = new SqlConnection(connString))
                    {
                        conn.Open();
                        SqlCommand cmd = new SqlCommand(sql, conn);
                        cmd.Parameters.Add(new SqlParameter("@count", count));
                        cmd.Parameters.Add(new SqlParameter("@id", id));
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            public void SetCountZero()
            {
                string connString = Properties.Settings.Default.Database;
                string sql = "update test.dbo.Dish set [Count]=0";
                using (SqlConnection conn = new SqlConnection(connString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(sql, conn);
                    cmd.ExecuteNonQuery();
                }
            }
        }

    localDb类中主要有6个方法:
    GetDishes方法,用来获取数据库中Dish表内所有数据,返回一个List<Dish>。
    GetRestaurant方法,用来获取数据库中Restaurant表内所有数据,返回一个List<Restaurant>。
    GetNameById方法,根据Id搜索数据库中Dish表内对应的Name。用于在选择点击“+1”“-1”按钮时,通过按钮绑定的Id获取相应菜品的Name,并且附加到预购清单文本框中。
    CountAddOne方法,用于在选择点击“+1”按钮时,将数据库表内对应Count属性值加一。
    CountSubOne方法,用于在选择点击“-1”按钮时,将数据库表内对应Count属性值减一。
    SetCountZero方法,用于在点击“下单”按钮时,将数据库表内所有Count属性值置零。

  4. 新增ViewModels文件夹,添加MainWindowViewModel类。
     class MainWindowViewModel:BindableBase
        {
            public MainWindowViewModel()
            {
                localDb = new localDb();
                DishInfo = localDb.GetDishes();
                RestaurantInfo = localDb.GetRestaurants();
                Name = RestaurantInfo.FirstOrDefault().Name;
                Address = RestaurantInfo.FirstOrDefault().Address;
                Phone = RestaurantInfo.FirstOrDefault().PhoneNumber;
                AddOneCommand = new DelegateCommand<int?>(t => AddOne(t));
                SubOneCommand = new DelegateCommand<int?>(t=>SubOne(t));
                OrderFinishCommand = new DelegateCommand(OrderFinish);
    
            }
            localDb localDb;
    
    
            private List<Dish> dishInfo;
            public List<Dish> DishInfo
            {
                get { return dishInfo; }
                set
                {
                    dishInfo = value;
                    RaisePropertyChanged("DishInfo");
                }
            }
    
            private List<Restaurant> restaurantInfo;
    
            public List<Restaurant> RestaurantInfo
            {
                get { return restaurantInfo; }
                set
                {
                    restaurantInfo = value;
                    RaisePropertyChanged("RestaurantInfo");
                }
            }
            private string name;
    
            public string Name
            {
                get { return name; }
                set
                {
                    name = value;
                    RaisePropertyChanged("Name");
                }
            }
            private string address;
    
            public string Address
            {
                get { return address; }
                set
                {
                    address = value;
                    RaisePropertyChanged("Address");
                }
            }
            private string phone;
    
            public string Phone
            {
                get { return phone; }
                set
                {
                    phone = value;
                    RaisePropertyChanged("Phone");
                }
            }
    
            private string  orderText;
    
            public string  OrderText
            {
                get { return orderText; }
                set
                {
                    orderText = value;
                    RaisePropertyChanged("OrderText");
                }
            }
    
    public DelegateCommand<int?> SubOneCommand { get; set; }
            public DelegateCommand<int?> AddOneCommand { get; set; }
    
            public DelegateCommand OrderFinishCommand { get; set; }
    
            public void SubOne(int? id)
            {
                localDb.CountSubOne(id);
                DishInfo = localDb.GetDishes();
                string name = localDb.GetNameById(id);
                int n = OrderText.IndexOf(name);
                if (n != -1)
                {
                    string s = OrderText.Remove(n, name.Length);
                    OrderText = s;
                }
                
            }
    
            public void AddOne(int? id)
            {
                localDb.CountAddOne(id);
                DishInfo = localDb.GetDishes();
                OrderText += localDb.GetNameById(id);
            }
    
            public void OrderFinish()
            {
                localDb.SetCountZero();
                DishInfo = localDb.GetDishes();
                System.IO.File.WriteAllText(@"D:\orders.txt", OrderText);
                OrderText = string.Empty;
            }

    MainWindowViewModel类中有6各属性:
    DishInfo接受List<Dish>,绑定主界面DataGrid的ItemsSource。
    RestaurantInfo接受List<Restaurant>,将内部值再分给Name、Address、Phone属性,分别绑定到主界面的TextBlock中。
    OrderText接受选择的菜品名称。

    3个命令:
    SubOneCommand,绑定DataGrid中选择栏中的“-1”按钮的Command。
    AddOneCommand,绑定DataGrid中选择栏中的“+1”按钮的Command。
    OrderFinishCommand,绑定“下单”按钮的Command。

    3个方法:
    SubOne,与SubOneCommand关联。SubOneCommand = new DelegateCommand<int?>(t=>SubOne(t));

    AddOne,与AddOneCommand关联。AddOneCommand = new DelegateCommand<int?>(t => AddOne(t));
    OrderFinish,与OrderFinishCommand关联。OrderFinishCommand = new DelegateCommand(OrderFinish);

  5. MainWindow.xaml.cs中给DataContext赋值。
    public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new MainWindowViewModel();
            }

     

  6. MainWindow.xaml中创建主画面布局。
       <Border Background="LightBlue">
            <Grid>
    
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="2*"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="0" Orientation="Horizontal">
                    <TextBlock Text="{Binding Name}" FontSize="40" FontStyle="Italic" 
                          Foreground="Green" FontWeight="Bold" Margin="10,10,0,10" VerticalAlignment="Center"/>
                    <TextBlock Text="---欢迎您!" FontSize="40" FontStyle="Italic" 
                           Foreground="Red" FontWeight="Bold" Margin="0,10,10,10" VerticalAlignment="Center"/>
                </StackPanel>
                <StackPanel Grid.Row="1" Orientation="Horizontal">
                    <TextBlock Text="地址:" FontSize="30" Margin="5,5,0,5" FontWeight="Black" Foreground="Brown" VerticalAlignment="Center"/>
                    <TextBlock Text="{Binding Address}" FontSize="30" FontWeight="Black" Margin="0,5,5,5" Foreground="Orange" VerticalAlignment="Center" />
                </StackPanel>
                <StackPanel Grid.Row="2" Orientation="Horizontal">
                    <TextBlock Text="电话:" FontSize="30" Margin="5,5,0,5" FontWeight="Black" Foreground="Blue"  VerticalAlignment="Center"/>
                    <TextBlock Text="{Binding Phone}" FontSize="30" FontWeight="Black" Margin="0,5,5,5" Foreground="Red" VerticalAlignment="Center" />
                </StackPanel>
                <DataGrid Grid.Row="3" ColumnWidth="*" AutoGenerateColumns="False" ItemsSource="{Binding DishInfo}"
                      CanUserAddRows="False" FontSize="25" BorderBrush="Black">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="序号" Binding="{Binding Id}"></DataGridTextColumn>
                        <DataGridTextColumn Header="菜品名称" Binding="{Binding Name}"></DataGridTextColumn>
                        <DataGridTextColumn Header="菜品种类" Binding="{Binding Catagory}"></DataGridTextColumn>
                        <DataGridTextColumn Header="客户评价" Binding="{Binding Comment}"></DataGridTextColumn>
                        <DataGridTextColumn Header="评分" Binding="{Binding Score}"></DataGridTextColumn>
                        <DataGridTemplateColumn Header="选择" >
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <DockPanel LastChildFill="True">
                                        <Button Content="-1" Width="40"  
                                               CommandParameter="{Binding Id}" 
                                                Command="{Binding DataContext.SubOneCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}"
                                               Background="Pink" Margin="5,5,0,5" DockPanel.Dock="Left"/>
                                        <Button Content="+1" Width="40" 
                                                CommandParameter="{Binding Id}" 
                                                Command="{Binding DataContext.AddOneCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}"
                                               Background="Pink" Margin="5" DockPanel.Dock="Right"/>
                                        <TextBox  Margin="5,5,0,5"  BorderBrush="Black" Text="{Binding Count}"/>
                                    </DockPanel>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                    </DataGrid.Columns>
                </DataGrid>
                <Grid Grid.Row="4" Margin="5">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto"></RowDefinition>
                        <RowDefinition Height="*"></RowDefinition>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition Width="auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0" Text="预购清单:" FontSize="30" Margin="5" />
                    <Button  Grid.Row="0" Grid.Column="1" Content="下单" Width="100" Command="{Binding OrderFinishCommand}"
                         FontSize="30" Margin="5" Height="45" Background="Blue" Foreground="Red"/>
                    <TextBox  Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" FontSize="20" TextWrapping="Wrap"
                                 BorderBrush="Black" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                              Text="{Binding OrderText}"/>
                </Grid>
    
    
            </Grid>
    
        </Border>

    我做的有点花里胡哨,肯定还是可以优化的。我觉得很关键的一点就是选择栏中的“+1”“-1”按钮的属性CommandParameter=“{Binding Id}”。
    在我们触发SubOneCommand<int?>传进来的参数就是CommandParameter。

  7. 这样就大功告成了。代码方面应该还是会有一些小bug,一些愚蠢的操作网友也就见笑了,总之一起讨论进步。
    源代码我就发百度网盘了。

    链接:https://pan.baidu.com/s/1xwepaXFXZT-ziHB17z0-cQ
    提取码:b1ft

posted @ 2021-07-22 11:29  李令君  阅读(306)  评论(0)    收藏  举报