簡體   English   中英

將ComboBox DataSource設置為枚舉並綁定SelectedValue

[英]Setting ComboBox DataSource to an enum and binding SelectedValue

我有點絕望,因為昨天它正在工作,但是今天它不再工作,請允許我解釋一下我要做什么:

我想將ComboBoxDataSource設置為特定枚舉中的所有枚舉值。 就像這樣:

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

無法在具有空ValueMember的ListControl中設置SelectedValue。

我知道它在黑暗中發掘,但是任何人都可以與我集思廣益並找出問題所在嗎? 提前致謝!

選項1

要將SelectedValue用於數據綁定,請創建一個Calss 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"));

您可以使包含public T Value { get; set; }通用DataItem<T> public T Value { get; set; } public T Value { get; set; } 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; }
}

好的,就是這種情況。 您正在正確綁定到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 (如在我的示例中回答您的另一個問題),並且不會有任何問題。

從我對窗體上的Exchange UserControls的答案的修改示例, 其中帶有數據綁定,顯示了案例和解決方案:

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);
        }
    }
}

您可能還會發現以下有用的線程自定義WinForms數據綁定與轉換器不能在可為null的類型上使用(雙精度)?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM