c# winforms:如何使用绑定源捕获 DGV 中的 checkbox.checked 事件?
c# winforms: how to catch checkbox.checked event in DGV with a bindingsource?
下面是一个演示程序,用于说明我在实际应用程序中遇到的问题。它是一个 DataGridView
和一个 BindingSource
到一个 class 的对象列表。
问题是:当我单击 CheckBox
时,CheckBox
会立即发生明显变化,但 invitation_property_changed()
方法只有在我单击其他单元格后才会被调用。我需要在 Checkbox.Checked
事件发生时立即获取它的等效项,以便我可以更新 UI 中的另一个控件。 (如果我更改 OTHERS
单元格,用户自然会点击 Enter 触发 PropertyChanged
事件 - 所以这个对用户来说很自然。)
下面是屏幕截图:
这是我的玩具代码:
namespace dgv_binding_test {
public partial class Form1 : Form {
BindingSource bindingsource_invitations = new BindingSource();
class an_invitation : INotifyPropertyChanged {
static int lastID = 0;
int _id;
string _name;
bool _rsvp;
int _others;
public int id() {
return _id;
}
public string NAME {
get { return _name; }
set {
_name = value;
NotifyPropertyChanged("NAME");
}
}
public bool RSVP {
get { return _rsvp; }
set {
_rsvp = value;
NotifyPropertyChanged("RSVP");
}
}
public int OTHERS {
get { return _others; }
set {
_others = value;
NotifyPropertyChanged("OTHERS");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public an_invitation(string a_name, bool a_rsvp, int others) {
_id = lastID++;
_name = a_name;
_rsvp = a_rsvp;
_others = others;
}
private void NotifyPropertyChanged(String propertyName = "") {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
List<an_invitation> invitations = new List<an_invitation>();
public Form1() {
InitializeComponent();
an_invitation ai = new an_invitation("harry", true, 3);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
ai = new an_invitation("heidi", false, 0);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
ai = new an_invitation("henry", false, 0);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
ai = new an_invitation("hazel", true, 0);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
BindingList<an_invitation> bindingList = new BindingList<an_invitation>(invitations);
bindingsource_invitations = new BindingSource(bindingList, null);
dataGridView1.DataSource = bindingsource_invitations;
dataGridView1.AutoGenerateColumns = true;
}
private void invitation_property_changed(object sender, PropertyChangedEventArgs e) {
Debug.Write("change for id: " + ((an_invitation)sender).id() + " property: " + e.PropertyName + " change: " + ((an_invitation)sender).NAME + " to: ");
if (e.PropertyName == "NAME") {
Debug.WriteLine(((an_invitation)sender).NAME);
} else if (e.PropertyName == "RSVP") {
Debug.WriteLine(((an_invitation)sender).RSVP.ToString());
} else if (e.PropertyName == "OTHERS") {
Debug.WriteLine(((an_invitation)sender).OTHERS.ToString());
}
}
}
}
感谢您的考虑。
对于这种情况,我发现的最简单的解决方案是处理 DataGridView.CellContentClick
和 DataGridView.CellContentDoubleClick
事件。您可以保留所有当前的代码。您需要为这两个事件添加一个句柄,当它是 CheckBox
单元格时结束单元格编辑。结束编辑将触发值更改,就像离开当前单元格一样。
this.dataGridView1.CellContentClick += DataGridView1_CellContentClick;
this.dataGridView1.CellContentDoubleClick += DataGridView1_CellContentClick;
private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (this.dataGridView1[e.ColumnIndex, e.RowIndex] is DataGridViewCheckBoxCell)
{
this.dataGridView1.EndEdit();
}
}
过早结束单元格的编辑可能会出现问题 - 例如,如果它是 TextBox
单元格 - 由于验证。但由于它只是 True
或 False
,因此在这种情况下没有实际意义。
下面是一个演示程序,用于说明我在实际应用程序中遇到的问题。它是一个 DataGridView
和一个 BindingSource
到一个 class 的对象列表。
问题是:当我单击 CheckBox
时,CheckBox
会立即发生明显变化,但 invitation_property_changed()
方法只有在我单击其他单元格后才会被调用。我需要在 Checkbox.Checked
事件发生时立即获取它的等效项,以便我可以更新 UI 中的另一个控件。 (如果我更改 OTHERS
单元格,用户自然会点击 Enter 触发 PropertyChanged
事件 - 所以这个对用户来说很自然。)
下面是屏幕截图:
这是我的玩具代码:
namespace dgv_binding_test {
public partial class Form1 : Form {
BindingSource bindingsource_invitations = new BindingSource();
class an_invitation : INotifyPropertyChanged {
static int lastID = 0;
int _id;
string _name;
bool _rsvp;
int _others;
public int id() {
return _id;
}
public string NAME {
get { return _name; }
set {
_name = value;
NotifyPropertyChanged("NAME");
}
}
public bool RSVP {
get { return _rsvp; }
set {
_rsvp = value;
NotifyPropertyChanged("RSVP");
}
}
public int OTHERS {
get { return _others; }
set {
_others = value;
NotifyPropertyChanged("OTHERS");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public an_invitation(string a_name, bool a_rsvp, int others) {
_id = lastID++;
_name = a_name;
_rsvp = a_rsvp;
_others = others;
}
private void NotifyPropertyChanged(String propertyName = "") {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
List<an_invitation> invitations = new List<an_invitation>();
public Form1() {
InitializeComponent();
an_invitation ai = new an_invitation("harry", true, 3);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
ai = new an_invitation("heidi", false, 0);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
ai = new an_invitation("henry", false, 0);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
ai = new an_invitation("hazel", true, 0);
ai.PropertyChanged += new PropertyChangedEventHandler(invitation_property_changed);
invitations.Add(ai);
BindingList<an_invitation> bindingList = new BindingList<an_invitation>(invitations);
bindingsource_invitations = new BindingSource(bindingList, null);
dataGridView1.DataSource = bindingsource_invitations;
dataGridView1.AutoGenerateColumns = true;
}
private void invitation_property_changed(object sender, PropertyChangedEventArgs e) {
Debug.Write("change for id: " + ((an_invitation)sender).id() + " property: " + e.PropertyName + " change: " + ((an_invitation)sender).NAME + " to: ");
if (e.PropertyName == "NAME") {
Debug.WriteLine(((an_invitation)sender).NAME);
} else if (e.PropertyName == "RSVP") {
Debug.WriteLine(((an_invitation)sender).RSVP.ToString());
} else if (e.PropertyName == "OTHERS") {
Debug.WriteLine(((an_invitation)sender).OTHERS.ToString());
}
}
}
}
感谢您的考虑。
对于这种情况,我发现的最简单的解决方案是处理 DataGridView.CellContentClick
和 DataGridView.CellContentDoubleClick
事件。您可以保留所有当前的代码。您需要为这两个事件添加一个句柄,当它是 CheckBox
单元格时结束单元格编辑。结束编辑将触发值更改,就像离开当前单元格一样。
this.dataGridView1.CellContentClick += DataGridView1_CellContentClick;
this.dataGridView1.CellContentDoubleClick += DataGridView1_CellContentClick;
private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (this.dataGridView1[e.ColumnIndex, e.RowIndex] is DataGridViewCheckBoxCell)
{
this.dataGridView1.EndEdit();
}
}
过早结束单元格的编辑可能会出现问题 - 例如,如果它是 TextBox
单元格 - 由于验证。但由于它只是 True
或 False
,因此在这种情况下没有实际意义。