Связывание данных WinForms
Я новичок в привязке данных.
У меня есть эти классы:
public class Foo : List<Bar>
{
public string FooName { get; set; }
}
public class Bar
{
public string BarName { get; set; }
public string BarDesc { get; set; }
}
И у меня есть List<Foo>
Я хотел бы иметь Foo
элементы в ComboBox
и Bar
элементы в ListBox
. Когда я изменяю выбранный элемент в ComboBox
, я хочу, чтобы ListBox
изменился. Когда я изменяю выбранный элемент в ListBox
, я хотел бы иметь TextBox
, заполненный BarDesc
.
Выполняется только для ListBox
и ComboBox
:
comboBox1.DataSource = foos;
comboBox1.DisplayMember = "FooName";
listBox1.DataBindings.Add("DataSource", foos, "");
listBox1.DisplayMember = "BarName";
Я не могу теперь привязать выбранное свойство Bar
в ListBox
к TextBox.Text
. Возможно, добавленная привязка для listBox1
- не очень хорошая идея.
Может быть, я должен сделать что-то вроде этого:
((CurrencyManager)listBox1.BindingContext[foos]).CurrentChanged += new EventHandler((o, a) =>
{
textBox1.DataBindings.Clear();
textBox1.DataBindings.Add("Text", listBox1.DataSource, "BarDesc");
});
Как я могу решить свою проблему?
Ответы
Ответ 1
Чтобы сделать все это, мне пришлось добавить свойство Items
в класс Foo
. Это "связь/связь" между двумя источниками привязки.
public partial class Form1 : Form {
public class Foo : List<Bar> {
public string FooName { get; set; }
public Foo(string name) { this.FooName = name; }
public List<Bar> Items { get { return this; } }
}
public class Bar {
public string BarName { get; set; }
public string BarDesc { get; set; }
public Bar(string name, string desc) {
this.BarName = name;
this.BarDesc = desc;
}
}
public Form1() {
InitializeComponent();
List<Foo> foos = new List<Foo>();
Foo a = new Foo("letters");
a.Add(new Bar("a", "aaa"));
a.Add(new Bar("b", "bbb"));
foos.Add(a);
Foo b = new Foo("digits");
b.Add(new Bar("1", "111"));
b.Add(new Bar("2", "222"));
b.Add(new Bar("3", "333"));
foos.Add(b);
//Simple Related Object List Binding
//http://blogs.msdn.com/bethmassi/archive/2007/04/21/simple-related-object-list-binding.aspx
BindingSource comboBoxBindingSource = new BindingSource();
BindingSource listBoxBindingSource = new BindingSource();
comboBoxBindingSource.DataSource = foos;
listBoxBindingSource.DataSource = comboBoxBindingSource;
listBoxBindingSource.DataMember = "Items";
comboBox1.DataSource = comboBoxBindingSource;
comboBox1.DisplayMember = "FooName";
listBox1.DataSource = listBoxBindingSource;
listBox1.DisplayMember = "BarName";
textBox1.DataBindings.Add("Text", listBoxBindingSource, "BarDesc");
}
}
Ответ 2
Используйте BindingSource для всех сложных требований к привязке данных:
// bind to List<Foo>
BindingSource comboBoxBindingSource = new BindingSource();
comboBoxBindingSource.DataSource = foos;
// use this binding source in comboBox1
// for display use FooName
comboBox1.DataSource = comboBoxBindingSource;
comboBox1.DisplayMember = "FooName";
// bind to comboBox1 SelectedValue
// it will point to the Foo selected in combobox
BindingSource listBoxBindingSource = new BindingSource();
listBoxBindingSource.DataSource = comboBox1;
listBoxBindingSource.DataMember = "SelectedValue";
// use this binding source in listBox1
// for display use BarName
listBox1.DataSource = listBoxBindingSource;
listBox1.DisplayMember = "BarName";
// bind to comboBox'1s SelectedValue (reusing listBoxBindingSource)
// and set Text to value of BarDesc
textBox1.DataBindings.Add("Text", listBoxBindingSource, "BarDesc");
Ответ 3
Вероятно, вы должны установить ValueMember в комбо и в поле списка. Возможно, вам также понадобится обработать bindingSource.CurrentChanged и переустановить список в текущий выбранный список.
Ответ 4
Отключить тему относительно наследования и композиции.
Вы эффективно говорите: "Foo - это список баров с именем", когда было бы намного проще сказать: "Foo имеет имя и имеет список баров". Но почему?
Что, если вы хотите сделать Foo двумя списками? Или список и словарь? С# не разрешает множественное наследование (которое само по себе грязно!), Поэтому вам придется идти и создавать другой класс, который в любом случае содержит несколько структур данных.
Также из-за наследования вам пришлось создать метод "Items", который возвращает себя, ненужный код.
Попробуй это:
public class Foo
{
public string FooName { get; set; }
public List<Bar> Items;
}