c# - C# - 防止在后续点击中调用按钮
问题描述
我有这个表格:
如果我按下右侧的黄色按钮,表格将变为:
当我修改元素并按“SALVA”按钮保存更改时,我得到了正确的行为:出现一个消息框,告诉我所有内容都已正确保存。如果现在我再次按下黄色按钮(不退出表单)并修改一个元素(它可能是相同的或另一个)我会得到一个不好的行为:消息框出现两次。如果我再做一次同样的事情,消息框会连续出现 3 次,以此类推。
查看函数调用者(我使用 this Console.WriteLine((new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name)
),我发现在第一次调用时,类型是 OnClick,从第二次调用开始,类型更改为 Invoke。结果,函数 SaveChange() 被多次调用。
我能做些什么来避免这种行为?
这是 cheActionsTable
类代码:
using Google.Protobuf.WellKnownTypes;
using office_software.DBModel;
using office_software.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace office_software.Table {
class ActionsTable<T, L> : TableLayoutPanel {
private readonly int y;
private readonly Form caller;
private readonly DBEntities dbEntities;
public ActionsTable(DBEntities dbEntities, Form caller, TableLayoutPanel parent, int x, int y, List<bool> type) {
this.y = y;
this.caller = caller;
this.dbEntities = dbEntities;
parent.Controls.Add(BuildTable(parent, type), x, y);
}
private TableLayoutPanel BuildTable(TableLayoutPanel parent, List<bool> type) {
TableLayoutPanel actionPanel = new TableLayoutPanel {
RowCount = 1,
ColumnCount = type.Where(x => x is true).ToList().Count,
Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom,
};
for (int k = 0; k < actionPanel.ColumnCount; k++) actionPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, (100 / actionPanel.ColumnCount)));
for (int k = 0; k < actionPanel.RowCount; k++) actionPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
int m = 0;
for (int l = 0; l < type.Count; l++) {
if (type[l]) {
Button button = new Button {
Anchor = AnchorStyles.None,
Height = 15,
Width = 15,
Name = $"{y}-{l}",
FlatStyle = FlatStyle.Flat,
BackColor = Constants.Constants.ACTIONS[l].color
};
ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(button, Constants.Constants.ACTIONS[l].actionName);
button.Click += (s, e) => ActionRow(s, e, parent);
actionPanel.Controls.Add(button, m, 0);
m++;
}
}
return actionPanel;
}
private void ShowDetails(List<string> data) {
if (typeof(L) != typeof(NullValue)) {
if (typeof(L) == typeof(DetailsForm)) {
DetailsForm details = new DetailsForm(dbEntities, new string[]{ data[0] });
details.ShowDialog();
}
else if (typeof(L) == typeof(CommissionDetailsForm)) {
CommissionDetailsForm details = new CommissionDetailsForm(dbEntities, new string[] { data[0].TrimStart('C') });
details.ShowDialog();
}
else if (typeof(L) == typeof(ProductDetails)) {
ProductDetails details = new ProductDetails(dbEntities, new string[]{ data[0] });
details.ShowDialog();
}
}
}
private void ModifyDetails(List<string> data) {
if (typeof(T) != typeof(NullValue)) {
if (typeof(T) == typeof(ProductsForm)) {
ProductsForm form = ((ProductsForm)caller);
form.titleLabel.Text = "MODIFICA PRODOTTO";
form.undoButton.Show();
form.addButton.Hide();
form.saveButton.Show();
form.model.Enabled = false;
string _tmp = data[0];
product product = dbEntities.products.FirstOrDefault(x => x.model.Equals(_tmp));
form.device.Text = product.device;
form.brand.Text = product.brand;
form.model.Text = product.model;
form.from.Text = product.range_from.ToString();
form.to.Text = product.range_to.ToString();
form.um.Text = product.unit_measure;
form.output.Text = product.output;
if (product.accuracy_rdg is null) {
form.accuracyType.SelectedIndex = 0;
form.percValue.Text = product.accuracy_fs.ToString();
}
else {
form.accuracyType.SelectedIndex = 1;
string[] tmp = product.accuracy_rdg.Replace(" ", "").Split('+');
form.percValue.Text = tmp[0].TrimEnd('%');
form.fixedValue.Text = tmp[1];
}
form.undoButton.Click += UndoModify;
form.saveButton.Click += SaveChange;
}
else if (typeof(T) == typeof(CustomersForm)) {
CustomersForm form = ((CustomersForm)caller);
form.titleLabel.Text = "MODIFICA CLIENTE";
form.undoButton.Show();
form.addButton.Hide();
form.saveButton.Show();
string _tmp = data[0];
customer customer = dbEntities.customers.FirstOrDefault(x => x.name.Equals(_tmp, StringComparison.OrdinalIgnoreCase));
form.name.Text = customer.name;
form.vatNumber.Enabled = false;
form.vatNumber.Text = customer.vat_number;
form.undoButton.Click += UndoModify;
form.saveButton.Click += SaveChange;
}
}
}
private void UndoModify(object sender, EventArgs e) {
if (typeof(T) != typeof(NullValue)) {
if (typeof(T) == typeof(ProductsForm)) {
ProductsForm form = ((ProductsForm)caller);
form.titleLabel.Text = "NUOVO PRODOTTO";
form.titleLabel.Select();
form.undoButton.Hide();
form.saveButton.Hide();
form.addButton.Show();
form.model.Enabled = true;
form.HandleTextBox(null);
}
else if (typeof(T) == typeof(CustomersForm)) {
CustomersForm form = ((CustomersForm)caller);
form.titleLabel.Text = "NUOVO CLIENTE";
form.titleLabel.Select();
form.undoButton.Hide();
form.saveButton.Hide();
form.addButton.Show();
}
}
}
private void SaveChange(object sender, EventArgs e) {
if (typeof(T) == typeof(ProductsForm)) {
ProductsForm form = ((ProductsForm)caller);
List<string> data = new List<string>();
form.HandleTextBox(data);
if (data.All(x => !string.IsNullOrEmpty(x))) {
product product = dbEntities.products.FirstOrDefault(p => p.model.Equals(form.model.Text, StringComparison.OrdinalIgnoreCase));
product.brand = form.brand.Text;
product.device = form.device.Text;
product.output = form.output.Text;
product.unit_measure = form.um.Text;
product.range_from = Convert.ToInt32(form.from.Text);
product.range_to = Convert.ToInt32(form.to.Text);
product.accuracy_fs = (form.accuracyType.SelectedIndex == 0) ? float.Parse(form.percValue.Text.Replace('.', ',')) : (float?)null;
product.accuracy_rdg = (form.accuracyType.SelectedIndex == 1) ? $"{form.percValue.Text}% + {form.fixedValue.Text}" : null;
dbEntities.SaveChanges();
MessageBox.Show("Prodotto modificato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);
form.productListTable.Controls[1].Dispose();
new CustomTable<ProductsForm, ProductDetails>(
dbEntities,
form,
form.productListTable,
new List<string> { "MODELLO", "SCALA", "USCITA" },
dbEntities.products.ToList().Select(x => new Row(x)).ToList(),
new List<bool> { true, true, true }
);
form.titleLabel.Text = "NUOVO PRODOTTO";
form.titleLabel.Select();
form.saveButton.Hide();
form.undoButton.Hide();
form.addButton.Show();
}
else MessageBox.Show("Tutti i campi sono obbligatori.", "ERRORE", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (typeof(T) == typeof(CustomersForm)) {
CustomersForm form = ((CustomersForm)caller);
if (!string.IsNullOrEmpty(form.name.Text)) {
customer customer = dbEntities.customers.FirstOrDefault(x => x.vat_number.Equals(form.vatNumber.Text, StringComparison.OrdinalIgnoreCase));
customer.name = form.name.Text;
dbEntities.SaveChanges();
MessageBox.Show("Cliente modificato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);
/*
form.customerParent.Controls[1].Dispose();
new CustomTable<CustomersForm, NullValue>(
dbEntities,
form,
form.customerParent,
new List<string> { "NOME", "PARTITA IVA" },
dbEntities.customers.OrderBy(x => x.name).ToList().Select(i => new Row(i)).ToList(),
new List<bool> { false, true, true }
);
form.titleLabel.Text = "NUOVO CLIENTE";
form.titleLabel.Select();
form.saveButton.Hide();
form.undoButton.Hide();
form.addButton.Show();
form.vatNumber.Enabled = true;
form.vatNumber.Text = "";
form.name.Text = "";*/
Start start = new Start(dbEntities);
form.Hide();
start.ShowDialog();
}
else MessageBox.Show("Compirare tutti i campi.", "ERRORE", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void RemoveRow(List<string> data) {
string tmp = data[0];
if (typeof(T) != typeof(NullValue)) {
if (typeof(T) == typeof(CustomersForm)) {
customer customer = dbEntities.customers.FirstOrDefault(x => x.name.Equals(tmp, StringComparison.OrdinalIgnoreCase));
int existsCalibrations = dbEntities.calibrations.Where(x => x.commission.order.customer.name.Equals(customer.name)).Where(x => x.tests.Any()).Count();
if (existsCalibrations > 0) {
DialogResult dr = MessageBox.Show("Sono state trovate delle calibrazioni associate a questo cliente. Pocedendo con la sua eliminazione verranno persi tutti i dati ad esso associati. Si desidera procedere comunque?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes) return;
}
else {
DialogResult dr = MessageBox.Show("Sicuro di voler eliminare questo cliente?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes) return;
}
dbEntities.customers.Remove(customer);
dbEntities.SaveChanges();
MessageBox.Show("Cliente eliminato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);
((CustomersForm)caller).customerParent.Controls[1].Dispose();
new CustomTable<CustomersForm, NullValue>(
dbEntities,
((CustomersForm)caller),
((CustomersForm)caller).customerParent,
new List<string> { "NOME", "PARTITA IVA" },
dbEntities.customers.OrderBy(x => x.name).ToList().Select(i => new Row(i)).ToList(),
new List<bool> { false, true, true }
);
}
else if (typeof(T) == typeof(ProductsForm)) {
product product = dbEntities.products.FirstOrDefault(x => x.model.Equals(tmp, StringComparison.OrdinalIgnoreCase));
int existsCalibrations = dbEntities.calibrations.Where(x => x.commission.model.Equals(product.model)).Where(x => x.tests.Any()).Count();
if (existsCalibrations > 0) {
DialogResult dr = MessageBox.Show("Sono state trovate delle calibrazioni associate a questo prodotto. Pocedendo con la sua eliminazione verranno persi tutti i dati ad esso associati. Si desidera procedere comunque?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes) return;
}
else {
DialogResult dr = MessageBox.Show("Sicuro di voler eliminare questo prodotto?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes) return;
}
dbEntities.products.Remove(product);
dbEntities.SaveChanges();
MessageBox.Show("Prodotto eliminato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);
((ProductsForm)caller).productListTable.Controls[1].Dispose();
new CustomTable<ProductsForm, ProductDetails>(
dbEntities,
((ProductsForm)caller),
((ProductsForm)caller).productListTable,
new List<string> { "MODELLO", "SCALA", "USCITA" },
dbEntities.products.ToList().Select(x => new Row(x)).ToList(),
new List<bool> { true, true, true }
);
}
else if (typeof(T) == typeof(InputForm)) {
tmp = tmp.TrimStart('C');
commission commission = dbEntities.commissions.FirstOrDefault(x => x.id.ToString().Equals(tmp));
int existingCalibrations = dbEntities.calibrations.Where(x => x.commission.id == commission.id).Where(x => x.tests.Any()).Count();
if (existingCalibrations > 0) {
DialogResult dr = MessageBox.Show("Sono state già eseguite alcune calibrazioni associate a questa commessa. Pocedendo con la sua eliminazione verranno persi tutti i dati ad essa associati. Si desidera procedere comunque?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes) return;
}
else {
DialogResult dr = MessageBox.Show("Sicuro di voler eliminare questa commessa?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes) return;
}
dbEntities.commissions.Remove(commission);
dbEntities.SaveChanges();
MessageBox.Show("Commessa eliminata con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);
((InputForm)caller).orderListTable.Controls[1].Dispose();
var list = dbEntities.commissions.ToList();
new CustomTable<InputForm, CommissionDetailsForm>(
dbEntities,
((InputForm)caller),
((InputForm)caller).orderListTable,
new List<string> { "ID", "ORDINE", "CLIENTE", "MODELLO", "ESEGUITE" },
list.Select(i => new Row(dbEntities, i)).ToList(),
new List<bool> { true, false, true }
);
}
}
}
private void ActionRow(object sender, EventArgs _, TableLayoutPanel parent) {
// [0] => riga
// [1] => azione
string[] information = ((Button)sender).Name.Split('-');
switch (Convert.ToInt32(information[1])) {
case 0:
ShowDetails(RowValuesByIndex(parent, Convert.ToInt32(information[0])));
break;
case 1:
ModifyDetails(RowValuesByIndex(parent, Convert.ToInt32(information[0])));
break;
case 2:
RemoveRow(RowValuesByIndex(parent, Convert.ToInt32(information[0])));
break;
default:
break;
}
}
private List<string> RowValuesByIndex(TableLayoutPanel panel, int index) {
List<string> data = new List<string>();
for (int i = 0; i < panel.RowCount; i++) {
for (int j = 0; j < panel.ColumnCount; j++) {
if (i == index) {
data.Add(panel.GetControlFromPosition(j, i).Text);
}
}
}
return data;
}
}
解决方案
每次单击以修改项目时,都会为 saveButton.Click 和 undoButton.Clock 事件添加事件处理程序。
form.undoButton.Click += UndoModify;
form.saveButton.Click += SaveChange;
这些事件永远不会被删除。要解决此问题,您应该在修改新表单时从所有其他表单中删除这些事件。
例如,您可以在 saveChange 方法结束时执行此操作。
form.saveButton.Click -= SaveChange;
推荐阅读
- c# - File.ReadAllText 抛出 DirectoryNotFoundException
- recursion - 在 Prolog 递归中正确使用 is/2 谓词
- android - 真人脸识别
- c++ - 包含 Linux 系统调用的单元测试代码
- java - 什么是 GenericTypeResolver 以及它是如何工作的?
- python - Django授权后端+总是返回'user.is_authenitcated' false
- java - 使用证书 .cer 在 Tomcat 上安装 SSL
- clearcase - 是否可以在vob中列出包含签出文件的视图?
- docker - 通过 Docker 客户端从主机连接到 Vagrant VM 中的 Docker 守护进程
- mongodb - 如何从 mongodb 获取嵌套数据