将Winforms控件数据绑定到可空类型的最佳方法?

时间:2008-12-17 22:55:55

标签: .net winforms data-binding nullable

我目前正在使用winforms数据绑定来连接数据编辑表单。我通过CodeSmith使用netTiers框架来生成我的数据对象。对于允许空值的数据库字段,它会创建可空类型。我发现使用winforms数据绑定控件将无法正确绑定到可空类型。

我在网上看过一些解决方案,建议人们创建可以处理可空类型的新文本框类,但是在我已经创建的表单上交换文本框可能会很麻烦。

最初我认为使用扩展方法来做这件事会很棒。基本上为文本框类创建扩展属性并绑定到该属性。从我有限的扩展方法经验和在网上做一些检查看起来你不能做扩展属性。据我所知,绑定必须通过属性,因为它需要能够获取或设置值,因此扩展方法不起作用。

我很想找到一种干净的方法来使用扩展方法来改造这些表单,但是如果我必须创建新的文本框和组合框控件那就是我要做的。

由于需要在Windows 2000上运行,我的项目目前仅限于.Net 2.0。

有什么建议吗?

4 个答案:

答案 0 :(得分:42)

在上面引用文章的评论部分中,其中一张海报提出了一个简单的解决方案。

而不是绑定:

textBox1.DataBindings.Add("Text", myClass, "MyTextProperty");

绑定:

textBox1.DataBindings.Add("Text", myClass, "MyTextProperty", true, DataSourceUpdateMode.OnPropertyChanged, string.Empty); 

答案 1 :(得分:5)

我自己偶然发现了这个问题并且真的很头疼。

绑定可空类型的有趣之处在于DataGridView可以毫无问题地处理它们 - 它只是导致问题的文本框。

这非常令人讨厌 - 当文本框中有一个空值时,它甚至可能会阻止关闭表单,而且看起来你也无法远离它。

所以,这不是一个很好的答案,但我的建议是尝试坚持表格中可空类型的datagridviews。

另一个建议是使用此处建议的“扩展程序提供程序”,但我尚未对其进行测试:

编辑:现在已经下载了此页面上的示例代码,它的工作原理是BRILLIANLY。

http://www.thejoyofcode.com/Databinding_and_Nullable_types_in_WinForms.NET.aspx

答案 2 :(得分:1)

哦,讨厌......我只能想到几种方法来实现这一目标,而且它们都不是我称之为理想的方式。

  • 第一种是为数据对象编写一个包装器,其中包含将所有nullables转换为空字符串的nullables。绑定到您的包装器对象。

  • 第二个是确保数据库中的所有值都不为空...再次,不理想

  • 在这种情况下你已经决定的第三个是不可行的是你创建一个自定义对象来扩展文本框以添加一个可以绑定到可空的属性。

  • 我能想到的第四种最理想的方式似乎不可能。创建一个扩展属性,允许您扩展所有文本框对象并绑定到该属性 - 但此时似乎不存在扩展属性。看起来这种类型的功能在.NET框架中特别有用。

答案 3 :(得分:0)

来自Databinding and Nullable types in WinForms.NET

场景

  • 您有一个具有Nullable属性的实体类型。
  • 您有一个绑定到该属性的TextBox。
  • 当用户清除TextBox中的文本时,您希望将属性值设置为null。

问题

清除绑定到Nullable类型的TextBox时,数据绑定的结果将仅不会成功。

解决方案

在本文中,我将向您展示如何使用扩展器提供程序。

只需将一个Component类添加到您的项目中,即可同时实现IExtenderProvider接口

[ProvideProperty("NullableBinding", typeof(TextBox))]  
public partial class NullableExtender : Component, IExtenderProvider

ProviderProperty属性指示在将NullableExtender组件添加到您的Form或UserControl时,所有TextBoxes将具有一个名为NullableBinding的附加属性。在VS.NET设计器中将如下所示:

NullableBinding Property

现在要为此属性实现一些功能:

private Dictionary<Control, Boolean> _nullables = new Dictionary<Control,bool>();

/// <summary>
/// This is the get part of the extender property.
/// It is actually a method because it takes the control.
/// </summary>
/// <param name="control"></param>
[DefaultValue(false),
Category("Data")]
public bool GetNullableBinding(Control control)
{
    bool nullableBinding = false;
    _nullables.TryGetValue(control, out nullableBinding);
    return nullableBinding;
}

/// <summary>
/// This is the set part of the extender property.
/// It is actually a method because it takes the control.
/// </summary>
/// <param name="control"></param>
/// <param name="nullable"></param>
public void SetNullableBinding(Control control, bool nullable)
{
    if (_nullables.ContainsKey(control))
        _nullables[control] = nullable;
    else
        _nullables.Add(control, nullable);
    if (nullable)
    {
        // Add a parse event handler.
        control.DataBindings["Text"].Parse += new ConvertEventHandler(NullableExtender_Parse);
    }
}

/// <summary>
/// When parsing, set the value to null if the value is empty.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void NullableExtender_Parse(object sender, ConvertEventArgs e)
{
    if (e.Value.ToString().Length == 0)
    {
        e.Value = null;
    }
}

实际上完成上述技巧的代码是为数据绑定Parse事件添加事件处理程序。如果该值是一个空字符串,则事件处理程序只需将该值设置为null即可,并且数据绑定成功。

该属性的默认值设置为false,因为大多数属性不是Nullable类型,我建议不要将这些属性的NullableBinding设置为true ...;)