BindingSource与Windows窗体中的通用子类

时间:2010-03-04 16:25:02

标签: c# winforms generics data-binding

我正在尝试做我认为BindingSource和ComboBox之间的简单数据绑定。当我使用的类作为BindingSource的DataSource有一个属性是泛型类的实例时,我遇到了问题。

我有以下通用类:

public class GenericClass<T>
{
    public T Code { get; set; }
    public string Description { get; set; }

    public override string ToString()
    {
        return Description;
    }
}

我有一个具有整数代码的类:

public class IntegerClass : GenericClass<int>
{
    // Nothing unique here, for simple test.
}

我还有一个设置为BindingSource的DataSource的类:

public class ClassBindingClass : INotifyProperty Changed
{
    private int _id;
    private IntegerClass _choice;
    private string _name;

    public int Id
    {
        get { return _id; }
        set
        {
            _id = value;
            OnPropertyChanged("Id");
        }
    }

    public IntegerClass Choice
    {
        get { return _choice; }
        set
        {
            _choice = value;
            OnPropertyChanged("Choice");
        }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertName));
    }
}

在我的表单上,我创建了一个IntegerClass的集合,并将combobox的{​​{1}}设置为该集合。 (这部分工作正常,组合框会正确显示值。)然后我将datasource的{​​{1}}绑定设置为combobox的{​​{1}}属性更新{ {1}}

如果我在组合框中选择一个值时将IntegerClass替换为非泛型类,则BindingSource的Choice属性会更改NotifyPropertyChanged事件被触发,在我的表单上我可以更新标签“选择已更改!”。 / p>

当IntegerClass是ClassBindingClass的一部分时,它不再起作用,而是我无法导航到组合框之外而是获得SelectedValue

我想做的是什么?数据绑定可以处理泛型吗?

1 个答案:

答案 0 :(得分:1)

你提到SelectedValue ...但你的源(和绑定属性)都是IntegerClass - 所以它不是你要绑定的,但是项目本身。不幸的是,没有ComboBox.SelectedItemChanged所以你可能需要破解它以获得双向绑定......

static class Program {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        IntegerClass[] choices = new[] {
            new IntegerClass { Code = 123, Description = "a b c"},
            new IntegerClass { Code = 456, Description = "d e f"},
            new IntegerClass { Code = 789, Description = "g h i"},
        };
        ComboBox cbo = new TwoWayComboBox();
        cbo.DropDownStyle = ComboBoxStyle.DropDownList;
        cbo.DataSource = choices;
        Form form = new Form();
        ClassBindingClass obj = new ClassBindingClass();
        cbo.DataBindings.Add("SelectedItem", obj, "Choice", true, DataSourceUpdateMode.OnPropertyChanged);
        form.DataBindings.Add("Text", obj, "Choice", true, DataSourceUpdateMode.OnPropertyChanged); // show it
        form.Controls.Add(cbo);
        Application.Run(form);


    }

}

class TwoWayComboBox : ComboBox {
    public new object SelectedItem
    {
        get { return base.SelectedItem; }
        set { base.SelectedItem = value; }
    }
    private static readonly object SelectedItemChangedKey = new object();
    public event EventHandler SelectedItemChanged {
        add { Events.AddHandler(SelectedItemChangedKey, value);}
        remove { Events.RemoveHandler(SelectedItemChangedKey, value);}
    }
    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        EventHandler handler = (EventHandler)Events[SelectedItemChangedKey];
        if (handler != null) { handler(this, EventArgs.Empty); }
        base.OnSelectedIndexChanged(e);
    }
}