【问题标题】:Setting ComboBox DataSource to an enum and binding SelectedValue将 ComboBox DataSource 设置为枚举并绑定 SelectedValue
【发布时间】:2015-10-07 16:47:20
【问题描述】:

我有点绝望,因为昨天它还在工作,但今天它不再工作了,让我解释一下,我想要做什么:

我想将ComboBox 的DataSource 设置为特定枚举中的所有枚举值。就这样:

cmbType.DataSource = m_addViewPresenter.Types;

其中 Types 是 BindingList 并且正在这样初始化:

public BindingList<MyEnum> Types
{
    get { return m_types; }
    set
    {
        m_types = value;
        OnPropertyChanged();
    }
}

[ImportingConstructor]
public AddViewPresenter()
{
    Types = new BindingList<MyEnum>(
              Enum.GetValues(typeof(MyEnum))
                         .Cast<MyEnum>().ToList());
}

此外,我想将当前选定的项目绑定到一个属性。由于ComboBox.SelectedItem 不会触发INotifyProperty 事件,我使用的是ComboBox.SelectedValue。

cmbType.Bind(m_addViewPresenter, c => c.SelectedValue, m => m.SelectedValue);

public static void Bind<TComponent, T>(
    this TComponent component, T value,
    Expression<Func<TComponent, object>> controlProperty, 
    Expression<Func<T, object>> modelProperty)
    where TComponent : IBindableComponent
    where T : INotifyPropertyChanged
{
    var controlPropertyName = PropertyNameResolver.GetPropertyName(controlProperty);
    var modelPropertyName = PropertyNameResolver.GetPropertyName(modelProperty);
    component.DataBindings.Add(new Binding(controlPropertyName, value, modelPropertyName, false, DataSourceUpdateMode.OnPropertyChanged));
}

昨天运行良好,但出了点问题,今天我只收到InvalidOperationException:

无法在 ListControl 中将 SelectedValue 设置为空 价值成员。

我知道它是在黑暗中挖掘,但是任何人都可以和我一起集思广益,找出问题所在吗?提前致谢!

【问题讨论】:

  • 看起来绑定到ComboBox.SelectedValue 需要设置'ComboBox.ValueMember`
  • 你真的应该绑定到ComboBox.SelectedItem,我不知道你为什么认为它不会触发属性更改通知,我认为它确实如此。
  • 我用 cmbType.Bind(m_addViewPresenter, c => c.SelectedValue, m => m.SelectedValue); 进行了尝试,但它没有进入 setter。 ://
  • @Jannik 要将数据绑定到SelectedValue,请使用另一个包含DisplayMember 属性和ValueMember 属性的类,并将您的枚举值调整为List&lt;ThatClass&gt;@987654337 @,或者只是将您的枚举值用作数据源并绑定到 SelectedItem,正如 Ivan 所提到的那样。
  • 就像我告诉你的那样,绑定 SelectedItem 不会进入 SelectedValue 的设置器,它不起作用。

标签: c# winforms data-binding combobox


【解决方案1】:

选项 1

要使用SelectedValue 进行数据绑定,请创建一个类DataItem:

public class DataItem
{
    public MyEnum Value { get; set; }
    public string Text { get; set; }
}

然后使用此代码进行数据绑定:

this.comboBox1.DataSource = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()
                                .Select(x => new DataItem() { Value = x, Text = x.ToString() })
                                .ToList();
this.comboBox1.ValueMember = "Value";
this.comboBox1.DisplayMember = "Text";

this.comboBox1.DataBindings.Add(
    new Binding("SelectedValue", yourObjectToBind, "PropertyOfYourObject"));

您可以使通用的DataItem&lt;T&gt; 包含public T Value { get; set; } 以使其在您的项目中更可重用。

选项 2

使用SelectedItem 进行数据绑定:

this.comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));
this.comboBox1.DataBindings.Add(
    new Binding("SelectedItem", yourObjectToBind, "PropertyOfYourObject"));

选项 3

要使用 SelectedValue 作为 Ivan Stoev 建议的另一个选项进行数据绑定,您可以通过这种方式执行数据绑定:

this.comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));
this.comboBox1.DataBindings.Add(
    new Binding("SelectedValue", yourObjectToBind, "PropertyOfYourObject",
                true,  DataSourceUpdateMode.OnPropertyChanged));

Jannik 编辑:

选项 1 的基本通用方法如下所示:

public class ComboBoxItemWrapper<T>
{
    public T Value { get; set; }
    public string Text { get; set; }
}

【讨论】:

  • 它工作正常,但有点烦人,你需要一个包装类。
  • @Jannik 感谢您接受答案,您可以通过将其设置为Generic 来使该类更易于重用,这样它就不会那么烦人了,或者可能很可爱。
  • @Jannik 不客气,我编辑了答案并提到了泛型,希望对您有所帮助:)
  • 该死,我也编辑了答案并添加了通用方法:D
  • 选项 1 和 2,包括通用方法,运行良好,谢谢。选项 3 不起作用,至少现在(VS 2022 with WinForms !!!)
【解决方案2】:

好的,情况就是这样。您正确绑定到ComboBox.SelectedValue。问题来自以下行:

component.DataBindings.Add(new Binding(controlPropertyName, value, modelPropertyName, false, DataSourceUpdateMode.OnPropertyChanged));

应该是

component.DataBindings.Add(new Binding(controlPropertyName, value, modelPropertyName, true, DataSourceUpdateMode.OnPropertyChanged));

简而言之,在使用 WF 数据绑定时,始终将 Binding.FormattingEnabled 设置为 true(如我回答您的另一个问题的示例),您不会遇到任何问题。

我对@9​​87654321@ 的回答的修改示例显示了案例和解决方案:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Tests
{
    enum MyEnum {  Red, Green, }
    class Controller
    {
        public MyEnum SelectedValue { get; set; }
    }
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var topPanel = new Panel { Dock = DockStyle.Top, Parent = form };
            var combo = new ComboBox { Left = 8, Top = 8, Parent = topPanel };
            topPanel.Height = combo.Height + 16;
            combo.DataSource = (MyEnum[])Enum.GetValues(typeof(MyEnum));
            var c = new Controller();
            combo.DataBindings.Add(new Binding("SelectedValue", c, "SelectedValue", true, DataSourceUpdateMode.OnPropertyChanged));
            form.BindingContextChanged += (sender, e) =>
            {
                // If you change combo binding formatting enabled parameter to false,
                // the next will throw the exception you are getting
                c.SelectedValue = MyEnum.Red;
            };
            var panel1 = new Panel { Dock = DockStyle.Fill, Parent = form, BackColor = Color.Red };
            var panel2 = new Panel { Dock = DockStyle.Fill, Parent = form, BackColor = Color.Green };
            Bind(panel1, "Visible", combo, "SelectedValue", value => (MyEnum)value == MyEnum.Red);
            Bind(panel2, "Visible", combo, "SelectedValue", value => (MyEnum)value == MyEnum.Green);
            Application.Run(form);
        }
        static void Bind(Control target, string targetProperty, object source, string sourceProperty, Func<object, object> expression)
        {
            var binding = new Binding(targetProperty, source, sourceProperty, false, DataSourceUpdateMode.Never);
            binding.Format += (sender, e) => e.Value = expression(e.Value);
            target.DataBindings.Add(binding);
        }
    }
}

您可能还会发现以下线程Custom WinForms data binding with converter not working on nullable type (double?) 有用

【讨论】:

  • 为了让答案更完整,我以这种方式在答案中添加了数据绑定选项,并在答案中提到了您。 +1
  • @RezaAghaei:比你,你也有我的 +1(因为我们似乎是最后的 WF 莫希干人之一 :-)
  • :D;) 让你大吃一惊
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
  • 2018-05-24
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多