【问题标题】:How can I prevent a RadioGroup from trying to set SelectedItem on Focus?如何防止 RadioGroup 尝试将 SelectedItem 设置为焦点?
【发布时间】:2017-08-14 20:45:37
【问题描述】:

我有一个用枚举值填充的 WinForms RadioGroup。我的问题是当控件获得焦点时,它会尝试使用System.DBNull 更新所选项目,这不是枚举的有效值,我最终得到了异常:

“System.DBNull”类型的对象无法转换为“MyNamespace.MyEnumType”类型

我有一个自定义 RadioGroup 类,其中包含以下用于添加项目和获取/设置所选值的代码:

/// <summary>
/// sets the items, using reflection to get the display member and value
/// </summary>
public void SetItems<T>(IEnumerable<T> values, string valueMember, string displayMember)
{
    Type t = typeof(T);

    PropertyInfo displayProperty = t.GetProperty(displayMember);
    PropertyInfo valueProperty = t.GetProperty(valueMember);

    if (displayProperty == null)
        throw new ArgumentException(string.Format("Property {0} is not found on class {1}", displayMember, t.FullName), "displayMember");

    if (valueMember == null)
        throw new ArgumentException(string.Format("Property {0} is not found on class {1}", valueMember, t.FullName), "valueMember");

    Properties.Items.Clear();

    foreach (var val in values)
    {
        object desc = displayProperty.GetValue(val, null);
        Properties.Items.Add(new RadioGroupItem(valueProperty.GetValue(val, null), desc == null ? string.Empty : desc.ToString()));
    }
}

/// <summary>
/// accessor for the selected value
/// </summary>
public object SelectedValue
{
    get { return GetSelectedValue(); }
    set { SetSelectedValue(value); }
}


private object GetSelectedValue()
{
    if (SelectedIndex < 0 || SelectedIndex >= Properties.Items.Count)
    {
        if (DataBindings.Count > 0 && DataBindings["SelectedValue"] != null)
            return DataBindings["SelectedValue"].DataSourceNullValue;
        else
            return null;
    }

    return Properties.Items[SelectedIndex].Value;
}

private void SetSelectedValue(object selectedItem)
{
    SelectedIndex = FindSelectedValue(selectedItem);
}

private int FindSelectedValue(object value)
{
    for (int i = 0; i < Properties.Items.Count; i++)
    {
        object val = Properties.Items[i].Value;

        if ((val != null && val.Equals(value)) || (val == null && value == null))
        {
            return i;
        }
    }

    return -1;
}

这是从文件后面的代码初始化它的方式:

myRadioGroup.SetItems<KeyValuePair<MyEnum, string>>(
    new List<KeyValuePair<MyEnum, string>>() 
    {
        new KeyValuePair<MyEnum, string>(MyEnum.VALUE_A, "Value A"), 
        new KeyValuePair<MyEnum, string>(MyEnum.VALUE_B, "Value B")
    },
"Key", "Value");

// adds the binding
myRadioGroup.DataBindings.Add(new Binding("MyPropertyName", myDataSource, "SelectedValue", true, DataSourceUpdateMode.OnValidation, MyEnum.NONE));

我不清楚为什么我打电话时会收到这个异常

myRadioGroup.Focus();

GotFocus 事件被触发,SetSelectedValue 方法被调用并返回一个正常的null 值。我唯一能想到的是GetSelectedValueDataSourceNullValue 显示为 System.DBNull,尽管在构造函数中将其设置为MyEnum.NONE,但即使我在调试模式下更正了它,它仍然会给我同样的异常。

也照MSDN page about this binding constructor

[空值参数]从数据源返回DBNull时,将属性设置为指定值。

这些是我唯一能看到对 DBNull 的引用的地方。

有没有办法修复这个异常,或者阻止 RadioGroup 在获得焦点时尝试更新数据源?

【问题讨论】:

  • RadioGroup 是什么?
  • 看看RadioButtonList。该帖子包含一个示例,展示了如何将它与枚举一起使用。
  • @RezaAghaei 正如您提供的链接所述,RadioButtonList 是 WebForms 控件,而不是 WinForms 控件。对于我正在开发的控件库,这不是一个合适的解决方案。
  • 查看我的答案,我提供了一个 Windows 窗体控件;)它实际上是一个单选 ListBox,它在项目附近显示单选按钮。因此它具有可靠的内置数据绑定支持。
  • @RezaAghaei 这不是一个坏主意,但我正在开发一个也建立在另一个第三方控件库上的控件库,所以我想要一个专门针对 RadioGroup 的解决方案。不过,也许其他时间值得研究一下,谢谢。

标签: c# winforms .net-3.5 radio-group


【解决方案1】:

我想我找到了解决方案...Binding 构造函数设置了.NullValue,而我需要设置.DataSourceNullValue

// adds the binding
Binding b = new Binding("MyPropertyName", myDataSource, "SelectedValue", true, DataSourceUpdateMode.OnValidation, MyEnum.NONE);
b.DataSourceNullValue = MyEnum.NONE;
myRadioGroup.DataBindings.Add(b);

根据this MSDN blog post

DataSourceNullValue 指定数据源的哪些值被视为空值,还指定应将哪些值写回数据源以获取空值

默认值为System.DBNull,因此它似乎试图将空值写入System.DBNull,这对于枚举无效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2011-02-11
    • 2013-10-04
    • 1970-01-01
    • 2012-05-13
    • 2021-09-13
    相关资源
    最近更新 更多