C# 如何将数据绑定与 Windows 窗体单选按钮一起使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/344964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use databinding with Windows Forms radio buttons?
提问by Coderer
I have a binary field in my database that is hard to describe in a UI using a single "Is XXXX?"-type checkbox. I'd rather use a pair of radio buttons (e.g. "Do it the Foo way" and "Do it the Bar way"), but right now all the other fields on my form are data-bound to a business object. I'd like to data-bind the pair of radio buttons to the business object as well, but haven't come up with a good way to do it yet. I can bind one of the buttons to the field, such that the field is set "true" if the button is selected, but while selecting the other button does de-select the first one (that is, the two radio buttons are properly paired), the value of the field does not update to reflect this.
我的数据库中有一个二进制字段,很难在 UI 中使用单个“是 XXXX 吗?”类型的复选框进行描述。我宁愿使用一对单选按钮(例如“Do it the Foo way”和“Do it the Bar way”),但现在我表单上的所有其他字段都绑定到业务对象。我也想将这对单选按钮数据绑定到业务对象,但还没有想出一个好的方法来做到这一点。我可以将其中一个按钮绑定到该字段,如果选择了该按钮,则该字段将设置为“true”,但是在选择另一个按钮时会取消选择第一个按钮(即,两个单选按钮已正确配对),该字段的值不会更新以反映这一点。
I'd like to be able to say
我想说
button1.DataBindings.Add(new Binding("checked", source, "useFoo"));
button2.DataBindings.Add(new Binding("checked", source, "!useFoo"));
but I'm pretty sure that will throw when it runs. Is there an easier way, or should I just put more thought into how to word a single checkbox? I don't want to add extra functions to handle something this trivial...
但我很确定它会在运行时抛出。有没有更简单的方法,或者我应该更多地考虑如何用单个复选框来表达?我不想添加额外的功能来处理这种微不足道的事情......
ETA: A commenter has suggested considering a dropdown (ComboBox). I had thought about this, but how would I data-bind that to a boolean field in a database/Property in a business object? If I bind the SelectedItem to the useFoo property, what would go in the Items collection? Would I have to add just "True" and "False", or could I somehow add a key/value pair object that ties a displayed item ("Use Foo" / "Do Not Use Foo") to the boolean value behind it? I'm having trouble finding docs on this.
ETA:一位评论者建议考虑使用下拉列表(ComboBox)。我曾经考虑过这个,但是我如何将它的数据绑定到业务对象中的数据库/属性中的布尔字段?如果我将 SelectedItem 绑定到 useFoo 属性,那么 Items 集合中会出现什么?我是否只需要添加“True”和“False”,或者我可以以某种方式添加一个键/值对对象,将显示的项目(“使用 Foo”/“不使用 Foo”)与其背后的布尔值联系起来?我很难找到这方面的文档。
About the answer: the solution I wound up using involved modifying the business object -- the basic idea is very similar to the one posted by Gurge, but I came up with it separately before I read his response. In short, I added a separate property that simply returns !useFoo
. One radio button is bound to source.UseFoo
, and the other is bound to source.UseBar
(the name of the new property). It's important to make sure the new property has both getters and setters, or you'll wind up with really odd behavior.
关于答案:我最终使用的解决方案涉及修改业务对象——基本思想与 Gurge 发布的非常相似,但我在阅读他的回复之前单独提出了它。简而言之,我添加了一个单独的属性,它只返回!useFoo
. 一个单选按钮绑定到source.UseFoo
,另一个绑定到source.UseBar
(新属性的名称)。确保新属性同时具有 getter 和 setter 是很重要的,否则最终会出现非常奇怪的行为。
采纳答案by Guge
I have found a way of doing this using DataSet/DataTable.
我找到了一种使用 DataSet/DataTable 做到这一点的方法。
I make a calculated column in the DataTable with the expression IIF(Foo=true, false, true)
. Let's call that column Bar
.
我使用表达式在 DataTable 中创建了一个计算列IIF(Foo=true, false, true)
。我们称其为 column Bar
。
Bar
is of type Boolean. Now you can bind one RadioButton.Checked
to Foo
and one to Bar
.
Bar
是布尔类型。现在您可以绑定一RadioButton.Checked
对Foo
和一对Bar
。
To get Bar
checking/unchecking to propagate back to Foo
you must go to the generated DataTable code and add one line, the last one in this sample:
要使Bar
检查/取消检查传播回Foo
您必须转到生成的 DataTable 代码并添加一行,即此示例中的最后一行:
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public bool Bar {
get {
try {
return ((bool)(this[this.tableradio.BarColumn]));
}
catch (global::System.InvalidCastException e) {
throw new global::System.Data.StrongTypingException("The value for column \'Bar\' in table \'radio\' is DBNull.", e);
}
}
set {
this[this.tableradio.BarColumn] = value;
this[this.tableradio.FooColumn] = !value;
}
}
回答by Excel Kobayashi
You should only have to bind one of the controls as long as you make sure they are in the same group.
只要确保它们在同一组中,您就应该只绑定其中一个控件。
You could also consider a DropDown.
您也可以考虑使用 DropDown。
回答by Guge
If your business object implements INotifyPropertyChanged (which makes binding work nicer), you can add the following code to the visual interface where BO
is your business object and is declared withevents and BO.Value
is the boolean property you would like to bind to.
如果您的业务对象实现了 INotifyPropertyChanged(这使得绑定工作得更好),您可以将以下代码添加到可视化界面中,其中BO
您的业务对象是您的业务对象,并且是用事件声明的,并且BO.Value
是您想要绑定到的布尔属性。
Public Property NotValue() As Boolean
Get
Return Not BO.Value
End Get
Set(ByVal value As Boolean)
BO.Value = Not value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
End Set
End Property
Private Sub BO_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles BO.PropertyChanged
If e.PropertyName = "Value" Then
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
End If
End Sub
The following bindings will hook up the radio buttons.
以下绑定将连接单选按钮。
RBTrue.DataBindings.Add(New Binding("Checked", Me.BO, "Value", False, DataSourceUpdateMode.OnPropertyChanged))
RBFalse.DataBindings.Add(New Binding("Checked", Me, "NotValue", False, DataSourceUpdateMode.OnPropertyChanged))
The visual interface should also implement INotifyPropertyChanged. This method works both ways: the original value gets updated if the interface changes and if the original value changes the interface will update correctly.
可视化界面还应实现 INotifyPropertyChanged。这种方法有两种作用:如果界面发生变化,原始值会更新,如果原始值发生变化,界面将正确更新。
回答by Mac
- Bind the
RadioButton
that is directly linked to your boolean value (ie is checked when the value istrue
). Add an event handler to the
CheckedChanged
event on thisRadioButton
that looks like the following :private void radioButton_CheckedChanged(object sender, EventArgs e) { foreach (Binding b in ((Control)sender).DataBindings) b.WriteValue(); }
- 绑定
RadioButton
直接链接到您的布尔值(即在值为 时检查true
)。 事件处理程序添加到
CheckedChanged
事件在这个RadioButton
看起来像下面这样:private void radioButton_CheckedChanged(object sender, EventArgs e) { foreach (Binding b in ((Control)sender).DataBindings) b.WriteValue(); }
回答by vi3x
I came across the same problem, and found out it's actually possible with standard databinding:
我遇到了同样的问题,并发现标准数据绑定实际上是可能的:
button1.DataBindings.Add(new Binding("checked", source, "useFoo", false, DataSourceUpdateMode.OnPropertyChanged);
// no need to databind button 2, since button1.checked
// is set to false when button2 is checked
By default, DataSourceUpdateMode
is set to OnValidation
. By setting it to OnPropertyChanged
, the change is propagated immediately to the databound object.
默认情况下,DataSourceUpdateMode
设置为OnValidation
。通过将其设置为OnPropertyChanged
,更改会立即传播到数据绑定对象。
My business object implements INotifyPropertyChanged
;
我的业务对象实现INotifyPropertyChanged
;
By testing this solution, I found out that my OnPropertyChanged
event was fired twice when I was clicking button2
. To prevent this, simply set
通过测试这个解决方案,我发现OnPropertyChanged
当我点击 时我的事件被触发了两次button2
。为了防止这种情况,只需设置
button1.CausesValidation = false;
button2.CausesValidation = false;
as shown here: TextBox leave causes PropertyChanged get fired twice
回答by Pete
Do it manually in code. When you load the form set your radio buttons according to your database. When you press a "save" button store de state as you wish. This example stores radios as bit fields in the database.
在代码中手动执行。当您加载表单时,根据您的数据库设置您的单选按钮。当您按下“保存”按钮时,您可以根据需要存储状态。此示例将无线电存储为数据库中的位字段。
// Load radio state
radioButton1.Checked = ((myModel)myBindingSource.DataSource).boolOption1;
radioButton2.Checked = ((myModel)myBindingSource.DataSource).boolOption2;
-
——
// Save radio state
((myModel)myBindingSource.DataSource).boolOption1 = radioButton1.Checked;
((myModel)myBindingSource.DataSource).boolOption2 = radioButton2.Checked;
I tried to drag items from the "Data Sources" panel in Visual Studio 2015 when I defined my radio buttons as booleans in the table but there is issues with the booleans not being updated to false when another radio button is selected. When changing the "causesValidation" to false radiobuttons unchecked automatically when jumping between other text input fields.
I tried to drag items from the "Data Sources" panel in Visual Studio 2015 when I defined my radio buttons as booleans in the table but there is issues with the booleans not being updated to false when another radio button is selected. 当在其他文本输入字段之间跳转时,将“causesValidation”更改为 false 单选按钮时会自动取消选中。