如何将数据绑定对象的组合框字段绑定到数据源并仍然允许空值?

时间:2022-02-25 21:12:06

I have a form databound to a customer object, and one of the fields is a nullable int representing a "type". This is displayed as a combobox, and the combobox is bound to the "Types" table.

我有一个表单数据绑定到客户对象,其中一个字段是一个可空的int表示“类型”。它显示为组合框,组合框绑定到“类型”表。

When a customer with a null type is loaded into the form's datasource, the combo box displays no value, but then upon clicking it you must select a value. The form/combobox will never let you change back to a blank item (to represent "null" on the customer object).

当具有null类型的客户加载到表单的数据源时,组合框不显示任何值,但在单击它时,您必须选择一个值。表单/组合框永远不会让您更改回空白项(在客户对象上表示“null”)。

I don't want "dummy rows" in the database, and currently do this by adding a dummy object, and nulling it out in a submit event (not clean!).

我不想在数据库中使用“虚拟行”,并且目前通过添加虚拟对象并在提交事件中将其清零(不干净!)来执行此操作。

Is it possible to do this cleanly, keeping with the nullable primary key?

是否可以干净利落地执行此操作,并保持可以为空的主键?

3 个解决方案

#1


The datasource which is used to bind to the Type combo, could have 1 more entry with NULL value in it.

用于绑定到Type组合的数据源可能还有1个带有NULL值的条目。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TypeID   Name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1        Business
2        Government
-1       NULL

You could store -1 for Customer who doesn't have a type (if it is allowed that a customer need not have a type).

您可以为没有类型的客户存储-1(如果允许客户不需要类型)。

#2


Additional links and resources concerning nullable databinding:

有关可空数据绑定的其他链接和资源:

I've been told and so far it has panned out, that you should have a layer of business objects in between your database datasource and your UI where you could just add an item as shahkalpesh recommends without concern of it going into the database.

我被告知,到目前为止它已经淘汰了,你应该在数据库数据源和UI之间有一层业务对象,你可以在shahkalpesh推荐的时候添加一个项目而不用担心它会进入数据库。

Jez Humble has some information on binding nullable types at the bottom of this post and in comments Where it suggests binding to nullable types is doable if "you explicitly set the DataSourceUpdateMode to DataSourceUpdateMode.OnPropertyChanged".

Jez Humble在本文的底部和注释中有关于绑定可空类型的一些信息如果“你明确地将DataSourceUpdateMode设置为DataSourceUpdateMode.OnPropertyChanged”,它建议绑定到可空类型是可行的。

Another article on databinding Nullable types: The Joy of Code - Databinding and Nullable types in WinForms.NET

关于数据绑定Nullable类型的另一篇文章:WinForms.NET中的Code of Joy - Databinding和Nullable类型

Maybe this code for binding a nullable DateTimePicker could help you find addditional solutions for this or other nullable issues.

也许这个用于绑定可空的DateTimePicker的代码可以帮助您找到针对此问题或其他可空问题的附加解决方案。

Also check out Dan Hannan for the source of where I came up with my extension method.

另请查看Dan Hannan,了解我提出扩展方法的来源。

/// <summary>
    /// From BReusable
    /// </summary>
    /// <param name="dtp"></param>
    /// <param name="dataSource"></param>
    /// <param name="valueMember"></param>
    /// <remarks>With help from Dan Hanan at http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx</remarks>
    public static void BindNullableValue(this DateTimePicker dateTimePicker, BindingSource dataSource, String valueMember,bool showCheckBox)
    {
        var binding = new Binding("Value", dataSource, valueMember, true);

        //OBJECT PROPERTY --> CONTROL VALUE
        binding.Format += new ConvertEventHandler((sender, e) =>
        {
            Binding b = sender as Binding;

            if (b != null)
            {
                DateTimePicker dtp = (binding.Control as DateTimePicker);
                if (dtp != null)
                {
                    if (e.Value == null)
                    {

                        dtp.ShowCheckBox = showCheckBox;
                        dtp.Checked = false;

                        // have to set e.Value to SOMETHING, since it's coming in as NULL
                        // if i set to DateTime.Today, and that's DIFFERENT than the control's current
                        // value, then it triggers a CHANGE to the value, which CHECKS the box (not ok)
                        // the trick - set e.Value to whatever value the control currently has. 
                        // This does NOT cause a CHANGE, and the checkbox stays OFF.

                        e.Value = dtp.Value;

                    }
                    else
                    {
                        dtp.ShowCheckBox = showCheckBox;
                        dtp.Checked = true;
                        // leave e.Value unchanged - it's not null, so the DTP is fine with it.
                    }

                }

            }
        });
        // CONTROL VALUE --> OBJECT PROPERTY
        binding.Parse += new ConvertEventHandler((sender, e) =>
        {
            // e.value is the formatted value coming from the control. 
            // we change it to be the value we want to stuff in the object.
            Binding b = sender as Binding;

            if (b != null)
            {
                DateTimePicker dtp = (b.Control as DateTimePicker);
                if (dtp != null)
                {
                    if (dtp.Checked == false)
                    {
                        dtp.ShowCheckBox = showCheckBox;
                        dtp.Checked = false;
                        e.Value = (Nullable<DateTime>)null;
                    }
                    else
                    {
                        DateTime val = Convert.ToDateTime(e.Value);
                        e.Value = val;
                    }
                }
            }
        });
        dateTimePicker.DataBindings.Add(binding);

    }

#3


If your main goal is to restore the combo to blank and the value to null, just press Ctrl+0 when editing the row.

如果您的主要目标是将组合恢复为空白并将值恢复为null,则在编辑行时只需按Ctrl + 0即可。

It took me two days of frantic research and heart attack risk just to find this out hidden in a small post somewhere.

我花了两天疯狂的研究和心脏病发作风险才发现隐藏在某个地方的小帖子里。

#1


The datasource which is used to bind to the Type combo, could have 1 more entry with NULL value in it.

用于绑定到Type组合的数据源可能还有1个带有NULL值的条目。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TypeID   Name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1        Business
2        Government
-1       NULL

You could store -1 for Customer who doesn't have a type (if it is allowed that a customer need not have a type).

您可以为没有类型的客户存储-1(如果允许客户不需要类型)。

#2


Additional links and resources concerning nullable databinding:

有关可空数据绑定的其他链接和资源:

I've been told and so far it has panned out, that you should have a layer of business objects in between your database datasource and your UI where you could just add an item as shahkalpesh recommends without concern of it going into the database.

我被告知,到目前为止它已经淘汰了,你应该在数据库数据源和UI之间有一层业务对象,你可以在shahkalpesh推荐的时候添加一个项目而不用担心它会进入数据库。

Jez Humble has some information on binding nullable types at the bottom of this post and in comments Where it suggests binding to nullable types is doable if "you explicitly set the DataSourceUpdateMode to DataSourceUpdateMode.OnPropertyChanged".

Jez Humble在本文的底部和注释中有关于绑定可空类型的一些信息如果“你明确地将DataSourceUpdateMode设置为DataSourceUpdateMode.OnPropertyChanged”,它建议绑定到可空类型是可行的。

Another article on databinding Nullable types: The Joy of Code - Databinding and Nullable types in WinForms.NET

关于数据绑定Nullable类型的另一篇文章:WinForms.NET中的Code of Joy - Databinding和Nullable类型

Maybe this code for binding a nullable DateTimePicker could help you find addditional solutions for this or other nullable issues.

也许这个用于绑定可空的DateTimePicker的代码可以帮助您找到针对此问题或其他可空问题的附加解决方案。

Also check out Dan Hannan for the source of where I came up with my extension method.

另请查看Dan Hannan,了解我提出扩展方法的来源。

/// <summary>
    /// From BReusable
    /// </summary>
    /// <param name="dtp"></param>
    /// <param name="dataSource"></param>
    /// <param name="valueMember"></param>
    /// <remarks>With help from Dan Hanan at http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx</remarks>
    public static void BindNullableValue(this DateTimePicker dateTimePicker, BindingSource dataSource, String valueMember,bool showCheckBox)
    {
        var binding = new Binding("Value", dataSource, valueMember, true);

        //OBJECT PROPERTY --> CONTROL VALUE
        binding.Format += new ConvertEventHandler((sender, e) =>
        {
            Binding b = sender as Binding;

            if (b != null)
            {
                DateTimePicker dtp = (binding.Control as DateTimePicker);
                if (dtp != null)
                {
                    if (e.Value == null)
                    {

                        dtp.ShowCheckBox = showCheckBox;
                        dtp.Checked = false;

                        // have to set e.Value to SOMETHING, since it's coming in as NULL
                        // if i set to DateTime.Today, and that's DIFFERENT than the control's current
                        // value, then it triggers a CHANGE to the value, which CHECKS the box (not ok)
                        // the trick - set e.Value to whatever value the control currently has. 
                        // This does NOT cause a CHANGE, and the checkbox stays OFF.

                        e.Value = dtp.Value;

                    }
                    else
                    {
                        dtp.ShowCheckBox = showCheckBox;
                        dtp.Checked = true;
                        // leave e.Value unchanged - it's not null, so the DTP is fine with it.
                    }

                }

            }
        });
        // CONTROL VALUE --> OBJECT PROPERTY
        binding.Parse += new ConvertEventHandler((sender, e) =>
        {
            // e.value is the formatted value coming from the control. 
            // we change it to be the value we want to stuff in the object.
            Binding b = sender as Binding;

            if (b != null)
            {
                DateTimePicker dtp = (b.Control as DateTimePicker);
                if (dtp != null)
                {
                    if (dtp.Checked == false)
                    {
                        dtp.ShowCheckBox = showCheckBox;
                        dtp.Checked = false;
                        e.Value = (Nullable<DateTime>)null;
                    }
                    else
                    {
                        DateTime val = Convert.ToDateTime(e.Value);
                        e.Value = val;
                    }
                }
            }
        });
        dateTimePicker.DataBindings.Add(binding);

    }

#3


If your main goal is to restore the combo to blank and the value to null, just press Ctrl+0 when editing the row.

如果您的主要目标是将组合恢复为空白并将值恢复为null,则在编辑行时只需按Ctrl + 0即可。

It took me two days of frantic research and heart attack risk just to find this out hidden in a small post somewhere.

我花了两天疯狂的研究和心脏病发作风险才发现隐藏在某个地方的小帖子里。