繁体   English   中英

如何用同一父处理不同的事件处理程序?

[英]How to handle different event handlers with same parent?

以下程序实际上不是我的项目,但是它使以后在实际程序中更容易理解我想要的内容。

这是一个.gif以查看当前功能:

我想要的是? 我要添加标签总分。 其中包括复选框和文本框的点,也应实时计算。 对于每个组(面板)

问题出在哪儿? 我不知道该如何管理,因为我正在使用两个不同的事件处理程序。

这是来源:

namespace Test1
{
    public partial class Form1 : Form
    {
        int chkBoxX = 10;
        int chkBoxY = 30;
        int txtBoxX = 10;
        int txtBoxY = 50;
        int panelX = 0;
        int panelY = 0;


        public Form1()
        {
            InitializeComponent();

            for (int k = 1; k <= 3; k++)
            {

                Panel panel = new Panel();
                panel.Width = 550;
                panel.Height = 100;
                panel.Location = new Point(panelX, panelY);
                panel.BackColor = Color.RoyalBlue;


                panelY += 110;

                 this.Controls.Add(panel);
                  AddElements(panel);

            }                                          

        }

        void AddElements(Panel panel) {

            Label labelChkBoxPoints = new Label();
            labelChkBoxPoints.Name = "labelChkBoxPoints";
            labelChkBoxPoints.Location = new Point(400, 30);
            labelChkBoxPoints.AutoSize = true;
            labelChkBoxPoints.BackColor = Color.White;
            labelChkBoxPoints.Font = new Font(labelChkBoxPoints.Font.FontFamily, 12, FontStyle.Bold);

            panel.Controls.Add(labelChkBoxPoints);

            Label labelTxtBoxPoints = new Label();
            labelTxtBoxPoints.Name = "labelTxtBoxPoints";
            labelTxtBoxPoints.Location = new Point(400, 50);
            labelTxtBoxPoints.AutoSize = true;
            labelTxtBoxPoints.BackColor = Color.White;
            labelTxtBoxPoints.Font = new Font(labelChkBoxPoints.Font.FontFamily, 12, FontStyle.Bold);

            panel.Controls.Add(labelTxtBoxPoints);

            Label labeltotalPoints = new Label();
            labeltotalPoints.Location = new Point(430, 40);
            labeltotalPoints.Font = new Font(labeltotalPoints.Font.FontFamily, 14, FontStyle.Bold);
      //      labeltotalPoints.Text = "10XXXXXXXXXXXX0";
            labeltotalPoints.AutoSize = true;
            labeltotalPoints.BackColor = Color.White;
                    //   labeltotalPoints.;
            panel.Controls.Add(labeltotalPoints);

            for (int i = 1; i <= 5; i++)
            {
                CheckBox checkBox = new CheckBox();
                checkBox.Name = String.Format("checkBox{0}", i);
                checkBox.Text = "";
                checkBox.Width = 20;
                checkBox.Height = 15;
                checkBox.Location = new Point(chkBoxX, chkBoxY);
                chkBoxX += 26;

                checkBox.CheckedChanged += checkBox_CheckedChanged;

                panel.Controls.Add(checkBox);

            }

            for (int j = 1; j <= 5; j++)
            {
                TextBox tb = new TextBox();
                tb.Name = String.Format("textBox{0}", j);
                tb.Width = 60;
                tb.Location = new Point(txtBoxX, txtBoxY);
                txtBoxX += 80;
                tb.TextChanged += txtBox_CheckedChanged;
                panel.Controls.Add(tb);
            }

            chkBoxX -= (5 * 26);
            txtBoxX -= (5 * 80);

        }

        private void txtBox_CheckedChanged(object sender, EventArgs e)
        {

            int total = 0; int points = 0; 

            foreach (object tb in ((TextBox)sender).Parent.Controls)
            {

                if (tb is TextBox)
                {
                    if (!string.IsNullOrEmpty(((TextBox)tb).Text))
                    {
                        if (!int.TryParse(((TextBox)tb).Text, out points))
                        {
                            ((TextBox)tb).Text = "";
                        }

                            total += points;
                    }
                }
            }

            (((TextBox)sender).Parent.Controls["labelTxtBoxPoints"]).Text = Convert.ToString(total);



        }

        private void checkBox_CheckedChanged(object sender, EventArgs e)
        {

            int counter = 0;

            foreach (object cb in ((CheckBox)sender).Parent.Controls)
            {
                if (cb is CheckBox)
                {
                    if (((CheckBox)cb).Checked)
                    {
                        counter++;
                    }
                }

            }

            (((CheckBox)sender).Parent.Controls["labelChkBoxPoints"]).Text = Convert.ToString(counter);

        }
    }
}

我将为此使用Microsoft的Reactive Framework(NuGet“ Rx-Main”和“ Rx-WinForms” /“ Rx-WPF”)。

它让我创建了几个函数,以一种相当紧凑的方式来实现您想要的功能。

对于复选框,您需要此功能:

Func<IEnumerable<CheckBox>, IObservable<int>> makeCheckBoxCounter = cbs =>
    cbs
        .Select(cb => Observable.FromEventPattern(h => cb.Click += h, h => cb.Click -= h))
        .Merge()
        .Select(ep => cbs.Where(cb2 => cb2.Checked == true).Count());

这使我可以将复选框列表传递给该函数,并返回IObservable<int> ,它为我提供了一个可观察到的序列,即复选框的总和。

您可以这样使用它:

IDisposable checkBoxesSubscription =
    makeCheckBoxCounter(new[] { checkBox1, checkBox2, checkBox3, checkBox4, checkBox5, })
        .Subscribe(x => label1.Text = x.ToString());

我已经测试过此代码,并且可以正常工作。

您可以通过调用以下命令将其关闭:

checkBoxesSubscription.Dispose();

文本框版本由于需要解析文本而稍微复杂一些。 看起来像这样:

Func<IEnumerable<TextBox>, IObservable<int>> makeTextBoxCounter = tbs =>
    tbs
        .Select(tb =>
            Observable
                .FromEventPattern(h => tb.TextChanged += h, h => tb.TextChanged -= h))
        .Merge()
        .Select(ep =>
        {
            var total = 0;
            foreach (var tb2 in tbs)
            {
                var value = 0;
                if (int.TryParse(tb2.Text, out value))
                {
                    total += value;
                }
            }
            return total;
        });

订阅是这样的:

var textBoxesSubscription =
    makeTextBoxCounter(new[] { textBox1, textBox2, textBox3, textBox4, textBox5, })
        .Subscribe(x => label2.Text = x.ToString());

我已经测试了这两个。

我将使用一个TextBox和一个static int totalTotalPoints =0;

添加带有每组标签的TextBlock

 void AddElements(Panel panel) {
    TextBlock textblock = new TextBlock();
    TextBlock.Name = "TBlock";

然后,在每个方法中对点进行更改的地方,更新TBlock.text();

 private void txtBox_CheckedChanged(object sender, EventArgs e)
 { ....
    total += points;
    // Implement a method to determine if points increase or decrease
    // of points change.
    // So if ( points -ve or if points +ve
    totalTotalPoints += points or -=points change;
     (((TextBlock)sender).Parent.Controls["TBlock"]).Text = Convert.ToString(totalTotalPoints);
 }

 private void checkBox_CheckedChanged(object sender, EventArgs e)
 { ...
    counter++;

    totalTotalPoints++;
    (((CheckBox)sender).Parent.Controls["TBlock"]).Text = Convert.ToString( totalTotalPoints);

 }

好。 这应该为您工作。

旁注:

创建面板时,动态分配它们的名称:

        for (int k = 1; k <= 3; k++)
        {
            Panel panel = new Panel();
            panel.Name = k.ToString();
            ...
        }   

您为什么不只在两个事件结束时计算“点”标签的总和?
很好而且很简单(您可以更有效地完成此操作,但我不知道这是有原因的...)
只需在checkBox_CheckedChanged,txtBox_CheckedChanged的末尾调用TotalPoints()

int TotalPoints()
{
        int total = (from i in GetControlsWithPoint(this)
                     where i.Text != null && i.Text != string.Empty
                     select Convert.ToInt32(i.Text)).Sum();
       // MessageBox.Show("total" + total);
        return total;
}

List<Control> GetControlsWithPoint(Control parent)
{
        List<Control> results = new List<Control>();
        if (parent == null)
            return results;

        foreach (Control item in parent.Controls)
        {
            if (item.Name == "labelChkBoxPoints" || item.Name == "labelTxtBoxPoints")
                results.Add(item);
            results.AddRange(GetControlsWithPoint(item));
        }

        return results;

 }

更新

如果只希望每个面板的总和,则只需更改TotalPoint方法以仅在面板内部进行搜索

 int TotalPoints(Panel p)
 {
        int total = (from i in GetControlsWithPoint(p) where i.Text != null && i.Text != string.Empty select Convert.ToInt32(i.Text)).Sum();
       // MessageBox.Show("total" + total);
        return total;
  }

在活动结束时

Panel p = (((Control)sender).Parent) as Panel;
TotalPoints(p);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM