![](/img/trans.png)
[英]C# winforms how to access the same object in different event handlers
[英]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.