You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF DataGrid餐厅账单:添加重复菜品时如何避免新增行仅更新Quantity列

Fixing Duplicate Rows in WPF DataGrid for Restaurant Bill Assignment

Hey there! I get exactly what you're dealing with—adding the same "Seafood Alfredo" and ending up with two rows instead of just updating the quantity is super frustrating. Let's sort this out step by step.

The Core Idea

Instead of immediately adding a new row every time the user clicks "Add", we first check if the selected main course already exists in our data collection. If it does, we just increment its Quantity value; if not, we add a brand new entry.

Step 1: Define Your Menu Item Model

First, you need a model class for your menu items that implements INotifyPropertyChanged—this ensures that when the quantity updates, the DataGrid automatically reflects the change:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class MenuItem : INotifyPropertyChanged
{
    private string _name;
    private decimal _price;
    private int _quantity;

    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }

    public decimal Price
    {
        get => _price;
        set { _price = value; OnPropertyChanged(); }
    }

    public int Quantity
    {
        get => _quantity;
        set { _quantity = value; OnPropertyChanged(); }
    }

    // Helper for property change notifications
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Step 2: Set Up Your Data Collection and Add Logic

In your window's code-behind (or ViewModel if you're using MVVM), you'll need an ObservableCollection<MenuItem> bound to your DataGrid. This collection automatically notifies the UI when items are added/removed or properties change.

Here's the code for the add button click handler:

using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;

public partial class RestaurantBillWindow : Window
{
    // This collection is bound to your DataGrid
    public ObservableCollection<MenuItem> BillItems { get; set; }

    public RestaurantBillWindow()
    {
        InitializeComponent();
        BillItems = new ObservableCollection<MenuItem>();
        DataContext = this; // Set data context so bindings work
    }

    private void AddMenuItem_Click(object sender, RoutedEventArgs e)
    {
        // Get the selected main course from your ComboBox
        if (MainCourseComboBox.SelectedItem is ComboBoxItem selectedItem)
        {
            string itemName = selectedItem.Content.ToString();
            decimal itemPrice = GetPriceForMenuItem(itemName);

            // Check if the item already exists in the bill
            var existingItem = BillItems.FirstOrDefault(item => item.Name == itemName);

            if (existingItem != null)
            {
                // Item exists—just increment quantity
                existingItem.Quantity += 1;
            }
            else
            {
                // Item doesn't exist—add a new row with quantity 1
                BillItems.Add(new MenuItem
                {
                    Name = itemName,
                    Price = itemPrice,
                    Quantity = 1
                });
            }
        }
    }

    // Helper method to get the price for a menu item (replace with your actual logic)
    private decimal GetPriceForMenuItem(string itemName)
    {
        // Example: hardcoded prices—you could load this from a database or config
        return itemName switch
        {
            "Seafood Alfredo" => 19.99m,
            "Steak Frites" => 24.99m,
            "Vegetarian Lasagna" => 16.99m,
            _ => 0m
        };
    }
}

Step 3: Update Your XAML

Make sure your DataGrid and ComboBox are properly bound to the collection and selected item:

<Window x:Class="RestaurantBillApp.RestaurantBillWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Restaurant Bill" Height="450" Width="800">
    <Grid>
        <!-- Main Course ComboBox -->
        <ComboBox x:Name="MainCourseComboBox"
                  HorizontalAlignment="Left" Margin="20,20,0,0" VerticalAlignment="Top" Width="200">
            <ComboBoxItem>Seafood Alfredo</ComboBoxItem>
            <ComboBoxItem>Steak Frites</ComboBoxItem>
            <ComboBoxItem>Vegetarian Lasagna</ComboBoxItem>
        </ComboBox>

        <!-- Add Button -->
        <Button Content="Add to Bill"
                HorizontalAlignment="Left" Margin="230,20,0,0" VerticalAlignment="Top"
                Click="AddMenuItem_Click"/>

        <!-- DataGrid for Bill Items -->
        <DataGrid x:Name="BillDataGrid"
                  ItemsSource="{Binding BillItems}"
                  AutoGenerateColumns="False"
                  Margin="20,60,20,20">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Main Course" Binding="{Binding Name}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Price" Binding="{Binding Price, StringFormat=C}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}"/>
                <DataGridTextColumn Header="Total" 
                                    Binding="{Binding Path=Price, StringFormat=C, Converter={StaticResource TotalConverter}}" 
                                    IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Key Notes

  • ObservableCollection: This is crucial because it tells the DataGrid when items are added/removed or when properties change (thanks to INotifyPropertyChanged on the model).
  • Checking for Existing Items: We use FirstOrDefault to look for an item with the same name as the selected one. If you have a unique ID for each menu item, use that instead of the name for more accuracy.
  • Property Change Notifications: The OnPropertyChanged method ensures that when we update Quantity, the DataGrid immediately shows the new value without needing to refresh the entire collection.

This should fix your duplicate row issue—now clicking "Add" on "Seafood Alfredo" will just bump the quantity up instead of creating a new row.

内容的提问来源于stack exchange,提问作者Psycho Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:20:22