winforms 从用户选择的复选框添加总计时出现问题

disho6za  于 2022-12-04  发布在  其他
关注(0)|答案(3)|浏览(169)

I am creating a form that allows the user to select from a group of checkboxes for automotive services. In the form, the user selects from a list of priced services and a final total is calculated based on what is selected.
The logic of the selected services being added up is placed within a method that returns the total.


.
Once the user clicks on the calculate button, all selected prices will be added up and displayed by the total fees label.

public partial class Automotive_Shop : Form
    {
        const int salesTax = (6 / 100);
        // prices for services
        const int
            oilChange = 26,
            lubeJob = 18,
            radiatorFlush = 30,
            transissionFlush = 80,
            inspection = 15,
            mufflerReplacement = 100,
            tireRotation = 20;

        int total = 0;

        public Automotive_Shop()
        {
            InitializeComponent();
        }



        private int OilLubeCharges()
        {
            if (oilChangeCheckBox.Checked == true)
            {
                total += oilChange;
            }                 
            if (lubeJobCheckBox.Checked == true)
            {
                total += lubeJob;
            }
          
            return total;
        }
           
      

      

        private void calculateButton_Click(object sender, EventArgs e)
        {
            totalFeesOutput.Text = OilLubeCharges().ToString("C");
                
        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            // close application
            this.Close();
        }
    }

The total should only be added once.
For instance: if the "oil change" check box is selected, then the total should be $26.
if the "lube job" check box is selected, then the total should be $18.
And if both check boxes are selected, then the total should be $44.
What ends up happening is that after the first check box is selected and the calculate button is clicked, the "total" variable value continues to be added up.
So if i select "oil change" then click calculate, I get $26. if I deselect it and select "lube job" the total doesn't equal $18, but $44.

2skhul33

2skhul331#

要解决此问题,需要在计算之前将total变量重置为0。
计算按钮单击事件应更新为如下所示:

private void calculateButton_Click(object sender, EventArgs e)
{
    total = 0;
    totalFeesOutput.Text = OilLubeCharges().ToString("C");
}
omtl5h9j

omtl5h9j2#

一个函数应该对它所做的一切负责,所以它所做的一切都应该在那里,不多不少。
这意味着当一个成员函数正在计算一个总计,并且在注解中您将其称为小计时,这就是该函数应该做的事情。
因此,您在函数int subtotal = 0;中声明并返回它。
然后,如果愿意,可以将其存储到成员变量中。
作为一个关于你的评论的例子,我已经添加了成员函数int ApplyDiscount(...)
它所做的唯一一件事就是对您传递的“a”小计应用折扣。对于一个工作应用程序来说,它应该得到改进。
在按钮处单击OilLubeCharges进行计算,然后将其传递到ApplyDiscount
这个返回值可以存储在一个全局变量中。您可以指定全部成本、价格折扣和总额。

// Added a functionality due to the comments
        // When `discount` is 0.2f for 20%
        private int ApplyDiscount(int subtotal, float discount)
        {
            return (int)( subtotal - ( subtotal * discount ) );
        }

        private int OilLubeCharges()
        {

            int subtotal = 0;

            if (oilChangeCheckBox.Checked == true)
            {
                subtotal += oilChange;
            }                 
            if (lubeJobCheckBox.Checked == true)
            {
                subtotal += lubeJob;
            }
          
            return subtotal;

        }

        ...

        private void calculateButton_Click(object sender, EventArgs e)
        {

            int subtotal = OilLubeCharges();
            int total = ApplyDiscount(subtotal, 0.2f);

            totalFeesOutput.Text = total.ToString("C");
                
        }
3duebb1j

3duebb1j3#

您提到了“所选服务的 * 逻辑 *......”,这个短语很有见地!考虑一种方法是将逻辑与 * 视图 * 分离(例如,允许与该逻辑交互的Form),因为很明显,当任何属性更改时,都会在某些其他属性中引起涟漪React,并且行为是定义良好的。放置在对所需行为进行建模的非UI类中,则可以使属性足够智能,以便在更改时发送通知事件。
例如,如果Parts的美元金额发生变更,则会触发Tax的重新计算,而Tax的新值会依次触发TotalFees属性的重新计算。

class AutoShopModel : INotifyPropertyChanged
{
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        switch (propertyName)
        {
            case nameof(Parts):
                recalcTax();
                break;
            case nameof(StandardServiceCharges):
            case nameof(Tax):
            case nameof(Labor):
                recalcTotalFees();
                break;
            default:
                recalcStandardServiceCharges();
                break;
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;        

    private void recalcTotalFees() =>
        TotalFees =
            StandardServiceCharges +
            Parts +
            Labor +
            Tax;
    .
    .
    .
}

这表明模型足够智能,无论哪些属性发生更改,都可以将相对值保持在一致的内部状态。然后,将更改同步到UI是一件简单的事情,只需将CheckBoxTextBox等控件绑定到模型中已设置为 bindable 的属性。
例如,OilChange属性只是一个bool,使其可绑定只是意味着在其值更改时触发一个事件:

partial class AutoShopModel
{
    public bool OilChange
    {
        get => _oilChange;
        set
        {
            if (!Equals(_oilChange, value))
            {
                _oilChange = value;
                OnPropertyChanged();
            }
        }
    }
    bool _oilChange = false;
    .
    .
    .
}

最后,在MainForm的Load方法中,checkBoxOilChange绑定到AutoShopModel.OilChange布尔值的更改,从而将所有内容粘合在一起:

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        Binding binding = new Binding(
            nameof(CheckBox.Checked), 
            AutoShopModel, 
            nameof(AutoShopModel.OilChange), 
            false, 
            DataSourceUpdateMode.OnPropertyChanged);
        checkBoxOilChange.DataBindings.Add(binding);
        .
        .
        .
    }
    AutoShopModel AutoShopModel { get; } = new AutoShopModel();
}

另外,当你制作Android或iOS版本的应用程序时,AutoShopModel是可移植和可重用的,因为它不引用任何特定于平台的UI元素。
如果您想尝试一下这个视图模型的想法,我将为您提供一个简短的演示。

相关问题