如何将数据绑定与 Windows 窗体单选按钮一起使用?

Posted

技术标签:

【中文标题】如何将数据绑定与 Windows 窗体单选按钮一起使用?【英文标题】:How do I use databinding with Windows Forms radio buttons? 【发布时间】:2010-09-25 14:08:44 【问题描述】:

我的数据库中有一个二进制字段,很难在 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"));

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

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


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

【问题讨论】:

【参考方案1】:
    绑定直接链接到布尔值的RadioButton(即当值为true时检查)。

    将事件处理程序添加到此 RadioButton 上的 CheckedChanged 事件,如下所示:

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

【讨论】:

【参考方案2】:

我找到了一种使用 DataSet/DataTable 的方法。

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

Bar 是布尔类型。现在您可以将一个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;
    

【讨论】:

并且不要忘记在每次编辑数据集时再次进行此更改! :-(【参考方案3】:

如果您的业务对象实现了 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

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

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

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

【讨论】:

【参考方案4】:

我遇到了同样的问题,发现标准数据绑定实际上是可能的:

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 leave causes PropertyChanged get fired twice

【讨论】:

【参考方案5】:

在代码中手动执行。当您加载表单时,根据您的数据库设置您的单选按钮。当您按下“保存”按钮时,可以根据需要存储状态。此示例将无线电作为位字段存储在数据库中。

        // 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中的“Data Sources”面板中拖动物品,当您在表中的Booleans定义了我的单选按钮时,但是在选择另一个单选按钮时,Booleans的问题没有更新为false。当在其他文本输入字段之间跳转时,将“causesValidation”更改为 false 单选按钮时自动取消选中。

【讨论】:

【参考方案6】:

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

您也可以考虑使用 DropDown。

【讨论】:

试试这个:制作一对单选按钮和一个复选框,并将一个单选按钮和复选框绑定到绑定源下的同一个布尔属性。选中复选框并切换收音机——没有任何反应。现在,如果您取消选中复选框,然后切换,您可以打开它,但永远不能关闭。

以上是关于如何将数据绑定与 Windows 窗体单选按钮一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 窗体中取消选择按钮或重新定义返回键的功能?

如何正确地将数据绑定到 Angular2 中的单选按钮?

如何在单选按钮上绑定数据

在 C# 中使用不同的父控件对 Windows 窗体单选按钮进行分组

如何以Windows格式动态添加单选按钮?

如何将 JRadioButton 组与模型一起使用