如何使用Windows窗体单选按钮进行数据绑定?

我的数据库中有一个二进制字段很难在UI中使用单个“Is XXXX?” – 类型复选框进行描述。 我宁愿使用一对单选按钮(例如“Do it the Foo way”和“Do it the Bar way”),但是现在我表单上的所有其他字段都是数据绑定到业务对象。 我想将这对单选按钮数据绑定到业务对象,但还没有找到一个好方法。 我可以将其中一个按钮绑定到该字段,这样如果选择了该按钮,则该字段设置为“true”,但是选择另一个按钮时取消选择第一个按钮(即,两个单选按钮正确配对) ),该字段的值不会更新以反映这一点。

我想能说

button1.DataBindings.Add(new Binding("checked", source, "useFoo")); button2.DataBindings.Add(new Binding("checked", source, "!useFoo")); 

但我很确定它会在它运行时抛出。 有没有更简单的方法,或者我应该更多地考虑如何单一复选框? 我不想添加额外的function来处理这个微不足道的事情……

ETA:一位评论者建议考虑下拉(ComboBox)。 我曾考虑过这个,但是我如何将它数据绑定到业务对象的数据库/属性中的布尔字段? 如果我将SelectedItem绑定到useFoo属性,那么Items集合中会包含什么? 我是否必须添加“True”和“False”,或者我可以以某种方式添加一个键/值对对象,将显示的项目(“使用Foo”/“不使用Foo”)绑定到它后面的布尔值? 我很难找到这方面的文档。


关于答案:我最后使用的解决方案涉及修改业务对象 – 基本思想与Gurge发布的基本思想非常相似,但在我阅读他的回复之前我分别想出了它。 简而言之,我添加了一个单独的属性,只返回!useFoo 。 一个单选按钮绑定到source.UseFoo ,另一个绑定到source.UseBar (新属性的名称)。 重要的是确保新房产既有吸气剂又有吸气剂,否则您将会遇到非常奇怪的行为。

我找到了一种使用DataSet / DataTable执行此操作的方法。

我使用表达式IIF在DataTable中创建一个计算列(Foo = true,false,true)。 我们称之为Bar Bar。

Bar的类型为Boolean。 现在你可以将一个radiobutton.checked绑定到Foo,将一个绑定到Bar。

要让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; } } 
  1. 绑定与您的布尔值直接相关的RadioButton (即,当值为true时检查)。
  2. 在此RadioButton上的CheckedChanged事件中添加一个事件处理程序,如下所示:

     private void radioButton_CheckedChanged(object sender, EventArgs e) { foreach (Binding b in ((Control)sender).DataBindings) b.WriteValue(); } 

如果您的业务对象实现了INotifyPropertyChanged(这使得绑定工作更好),您可以将以下代码添加到可视化接口,其中BO是您的业务对象并且声明为withevents而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 

以下绑定将连接单选按钮。

 RBTrue.DataBindings.Add(New Binding("Checked", Me.BO, "Value", False, DataSourceUpdateMode.OnPropertyChanged)) RBFalse.DataBindings.Add(New Binding("Checked", Me, "NotValue", False, DataSourceUpdateMode.OnPropertyChanged)) 

可视界面还应实现INotifyPropertyChanged。 此方法有两种方式:如果接口更改,原始值将更新,如果原始值更改,则接口将正确更新。

我遇到了同样的问题,并发现它实际上可以使用标准数据绑定:

 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 

默认情况下, DataSourceUpdateMode设置为OnValidation 。 通过将其设置为OnPropertyChanged ,更改将立即传播到数据绑定对象。

我的业务对象实现了INotifyPropertyChanged ;

通过测试此解决方案,我发现当我单击button2时,我的OnPropertyChanged事件被触发了两次。 为防止这种情况,请简单设置

 button1.CausesValidation = false; button2.CausesValidation = false; 

如下所示: TextBox离开导致PropertyChanged被触发两次

在代码中手动执行。 加载表单时,根据数据库设置单选按钮。 当您按下“保存”按钮存储de state时,如您所愿。 此示例将无线电存储为数据库中的位字段。

  // 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; 

当我在桌面中将单选按钮定义为布尔值时,我尝试从Visual Studio 2015中的“数据源”面板拖动项目,但是当选择另一个单选按钮时,布尔值没有更新为假的问题。 在其他文本输入字段之间跳转时,将“causeValidation”更改为false radiobuttons时会自动取消选中。

只要确保它们位于同一组中,您就应该只需绑定其中一个控件。

你也可以考虑DropDown。