BindingSource с универсальным подклассом в Windows Forms - PullRequest
2 голосов
/ 04 марта 2010

Я пытаюсь сделать то, что считал простым связыванием данных между BindingSource и ComboBox. Я сталкиваюсь с проблемами, когда класс, который я использую в качестве источника данных BindingSource, имеет свойство, которое является экземпляром универсального класса.

У меня есть следующий родовой класс:

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:

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 datasource для этой коллекции. (Эта часть работает нормально, поле со списком отображает значения соответствующим образом.) Затем я установил привязку combobox s SelectedValue к обновлению свойства BindingSource s Choice на OnPropertyChanged.

Если я заменю IntegerClass неуниверсальным классом, когда вы выбираете значение в поле со списком, свойство Choice BindingSource изменяет событие NotifyPropertyChanged, и в моей форме я могу обновить метку, говорящую «Выбор изменился!».

Когда IntegerClass является частью ClassBindingClass, это больше не работает, и вместо этого я не могу перейти из поля со списком и вместо этого получить FormatException.

Возможно ли то, что я хочу сделать? Может ли привязка данных обрабатывать дженерики?

1 Ответ

1 голос
/ 04 марта 2010

Вы упоминаете 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...