C# WinForm:将多个NumericUpDown数值累加至Label的实现求助
解决WinForm中NumericUpDown数值变化自动累加价格并存储的问题
嘿,作为从HTML转过来的C#新手,刚开始接触WinForm的事件驱动模式确实会有点懵,我来帮你搞定这个价格自动计算和数据存储的问题!
先说说你原代码里的几个小问题
- 累加逻辑有bug:你之前写的是每次数值变化就往总价里加当前控件的总价,但如果用户把数值调小(比如从3改成1),总价不会自动减少,只会越算越多
- 代码冗余:十几个
ValueChanged事件分开写,后期维护起来要疯 - 字符串解析价格容易出错:从
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
相关产品推荐
相关产品推荐

