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

C# WinForm:将多个NumericUpDown数值累加至Label的实现求助

解决WinForm中NumericUpDown数值变化自动累加价格并存储的问题

嘿,作为从HTML转过来的C#新手,刚开始接触WinForm的事件驱动模式确实会有点懵,我来帮你搞定这个价格自动计算和数据存储的问题!

先说说你原代码里的几个小问题

  1. 累加逻辑有bug:你之前写的是每次数值变化就往总价里加当前控件的总价,但如果用户把数值调小(比如从3改成1),总价不会自动减少,只会越算越多
  2. 代码冗余:十几个ValueChanged事件分开写,后期维护起来要疯
  3. 字符串解析价格容易出错:从price.Text里替换符号再解析,很容易因为格式问题抛出异常,而且没必要——直接用decimal变量存总价才是正确姿势

给你一套完整的解决方案

第一步:用字典管理药品单价(比switch清爽100倍)

先在你的Medication类里定义一个字典,把每个NumericUpDown控件和对应的单价绑定起来,后续新增药品直接加一行就行:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Task3
{
    public partial class Medication : Form
    {
        // 定义字典存储每个药品控件对应的单价
        private Dictionary<NumericUpDown, decimal> _medicationPrices = new Dictionary<NumericUpDown, decimal>()
        {
            { UpdownAntibiotic7, 19.60m },
            { UpdownAntibiotic14, 35.20m }, // 这里的价格你替换成实际案例里的数值
            { UpdownFleeAndMite, 22.50m },
            { UpdownHeartworm, 45.00m },
            { UpdownAnesGasTo30min, 50.00m },
            { UpdownAnesGasAfter30min, 20.00m },
            { UpdownFentanyl, 15.80m },
            { UpdownFrontline, 30.00m },
            { UpDownAnalgesia, 28.00m },
            { UpDownBaytrill, 18.50m },
            { UpDownMetronidazole, 12.30m },
            { UpDownRimadyl, 40.00m },
            { UpDownDrontalSmall, 14.90m },
            { UpDownDrontalLarge, 24.90m },
            { UpDownCanineRabies, 38.00m }
        };

        public Medication()
        {
            InitializeComponent();
            // 给所有药品控件绑定同一个数值变化事件
            foreach (var nud in _medicationPrices.Keys)
            {
                nud.ValueChanged += MedicationQuantity_Changed;
            }
            // 窗体加载时先算一次初始总价
            UpdateTotalPrice();
        }

第二步:写统一的计算和更新方法

不用每个控件写单独的事件,所有数值变化都触发同一个方法,重新计算所有药品的总价:

// 计算所有药品的总价
        private decimal CalculateTotal()
        {
            decimal total = 0;
            foreach (var item in _medicationPrices)
            {
                // 数量 × 单价,累加到总价
                total += item.Key.Value * item.Value;
            }
            return total;
        }

        // 更新总价Label的显示
        private void UpdateTotalPrice()
        {
            decimal total = CalculateTotal();
            // 假设你用来显示总价的Label叫lblTotalPrice,替换成你实际的控件名
            lblTotalPrice.Text = total.ToString("C"); // "C"会自动格式化成带£的货币格式
        }

        // 所有NumericUpDown共用的数值变化事件
        private void MedicationQuantity_Changed(object sender, EventArgs e)
        {
            // 只要任何一个数值变了,就重新计算并更新总价
            UpdateTotalPrice();
        }

第三步:实现数据存储(传递到下一个窗体或保存)

比如点击Next按钮时,把当前所有药品的数量和总价存起来,传递给下一个窗体:
首先定义一个用来存储订单数据的类(放在Task3命名空间下就行):

// 用来存储用药订单数据的类
public class MedicationOrder
{
    public int Antibiotic7Days { get; set; }
    public int Antibiotic14Days { get; set; }
    public int FleeAndMite { get; set; }
    public int Heartworm { get; set; }
    public int AnesGasTo30min { get; set; }
    public int AnesGasAfter30min { get; set; }
    public int Fentanyl { get; set; }
    public int Frontline { get; set; }
    public int Analgesia { get; set; }
    public int Baytrill { get; set; }
    public int Metronidazole { get; set; }
    public int Rimadyl { get; set; }
    public int DrontalSmall { get; set; }
    public int DrontalLarge { get; set; }
    public int CanineRabies { get; set; }
    public decimal TotalPrice { get; set; }
}

然后修改Next按钮的点击事件,把数据填充到这个类里:

private void btnNextForm3_Click(object sender, EventArgs e)
        {
            // 填充订单数据
            MedicationOrder currentOrder = new MedicationOrder()
            {
                Antibiotic7Days = (int)UpdownAntibiotic7.Value,
                Antibiotic14Days = (int)UpdownAntibiotic14.Value,
                FleeAndMite = (int)UpdownFleeAndMite.Value,
                Heartworm = (int)UpdownHeartworm.Value,
                AnesGasTo30min = (int)UpdownAnesGasTo30min.Value,
                AnesGasAfter30min = (int)UpdownAnesGasAfter30min.Value,
                Fentanyl = (int)UpdownFentanyl.Value,
                Frontline = (int)UpdownFrontline.Value,
                Analgesia = (int)UpDownAnalgesia.Value,
                Baytrill = (int)UpDownBaytrill.Value,
                Metronidazole = (int)UpDownMetronidazole.Value,
                Rimadyl = (int)UpDownRimadyl.Value,
                DrontalSmall = (int)UpDownDrontalSmall.Value,
                DrontalLarge = (int)UpDownDrontalLarge.Value,
                CanineRabies = (int)UpDownCanineRabies.Value,
                TotalPrice = CalculateTotal()
            };

            // 把订单数据传递给下一个窗体(需要在Procedures窗体里加一个MedicationOrder属性)
            Procedures nextForm = new Procedures();
            nextForm.CurrentMedicationOrder = currentOrder;
            this.Hide();
            nextForm.Show();
        }

最后把你原来的其他按钮事件保留就行:

private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnPrevious_Click(object sender, EventArgs e)
        {
            Form Start = new ClientData();
            this.Hide();
            Start.Show();
        }
    }
}

为什么这样做更好?

  • 避免重复代码:所有数值变化共用一个事件,不用写十几个几乎一样的方法
  • 计算逻辑更准确:每次重新计算所有药品的总价,不管用户调大还是调小数值,总价都会正确更新
  • 维护更简单:新增药品只需要在字典里加一行,不用改计算逻辑
  • 数据存储更规范:用类来管理订单数据,不管是传递到其他窗体还是保存到文件/数据库都很方便

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:30:29