IDictionary класса отображается в таблице C#
У меня есть IDictionary
который содержит постоянно меняющийся список моего класса, и я хочу отобразить коллекцию в пользовательском интерфейсе winforms, вероятно, с использованием DataGridView
или другой контроль. Я планирую иметь таймер, который обновляет таблицу каждые 1-2 секунды и кнопку паузы. при щелчке по любой строке мне нужно получить класс из словаря или вернуть первое поле, которое будет ключом в IDictionary
,
Итак, я создаю IDictionary
таким образом:
public static IDictionary<string, AClass> aList = new Dictionary<string, AClass>();
AClass
это простая коллекция строк:
public class AClass
{
public string data1{ get; set; }
public string data2{ get; set; }
}
Я добавляю AClass
к IDictionary
таким образом:
if (!MainForm.aircraftList.ContainsKey(strMyData))
{
MainForm.aList[strMyData] = new AClass{ data1= strMyData};
}
Как я могу создать таблицу со всеми столбцами из AClass
которые около 12 и рядами от IDictionary
Список, в котором есть переменное число, колеблется около 100.
2 ответа
Чтобы помочь вам начать, ниже приведен код, который использует DataGridView
для отображения данных с помощью DataTable
; List<AClass>
объекты, а также с помощью Dictionary<string, AClass>
, Как я уже сказал, используя словарь, вам придется сделать несколько дополнительных шагов, чтобы получить AClass
Value
из словаря. Эти дополнительные шаги указывают на то, что Словарь не обязательно является лучшей структурой данных для использования в качестве DataSource
если в вашем классе несколько переменных
Код ниже использует DataGridView
и четыре (4) кнопки. Есть кнопки для отображения данных в DataGridView
используя DataTable
; List<AClass>
(добавил ключ) и Dictionary<string, AClass>
и, наконец, кнопка для очистки DataGridView
Надеюсь это поможет.
public Dictionary<string, AClass> DGVDictionary;
public DataTable DGVTable;
public List<AClass> DGVList;
public Form1() {
InitializeComponent();
}
private Dictionary<string, AClass> GetDictionary() {
Dictionary<string, AClass> dictionary = new Dictionary<string, AClass>();
for (int key = 0; key < 15; key++) {
AClass ac = new AClass();
ac.data1 = "data1" + key;
ac.data2 = "data2" + key;
dictionary.Add(key.ToString(), ac);
}
return dictionary;
}
private void CreateTable() {
DGVTable = new DataTable();
DGVTable.Columns.Add("key", typeof(int));
DGVTable.Columns.Add("data1", typeof(string));
DGVTable.Columns.Add("data2", typeof(string));
}
private void FillDataTable() {
for (int key = 0; key < 15; key++) {
AClass ac = new AClass();
ac.data1 = "data1" + key;
ac.data2 = "data2" + key;
DGVTable.Rows.Add(key, ac.data1, ac.data2);
}
}
private List<AClass> FillList() {
List<AClass> list = new List<AClass>();
for (int key = 0; key < 15; key++) {
AClass ac = new AClass();
ac.key = key;
ac.data1 = "data1" + key;
ac.data2 = "data2" + key;
list.Add(ac);
}
return list;
}
private void buttonDataTable_Click(object sender, EventArgs e) {
CreateTable();
FillDataTable();
dataGridView1.DataSource = DGVTable;
MessageBox.Show("DGV with a DataTable");
}
private void buttonList_Click(object sender, EventArgs e) {
DGVList = FillList();
dataGridView1.DataSource = DGVList;
MessageBox.Show("DGV with a List<AClass>");
}
private void buttonDictionary_Click(object sender, EventArgs e) {
DGVDictionary = GetDictionary();
dataGridView1.DataSource = DGVDictionary.ToList();
MessageBox.Show("DGV with a Dictionat<string, AClass>");
}
private void buttonClear_Click(object sender, EventArgs e) {
dataGridView1.DataSource = null;
}
Поскольку вы используете IDictionary, механизм привязки по умолчанию не сможет получить отдельные записи или свойства класса AClass. Вы можете создать собственный BindingSource для выполнения этих задач.
Основная ответственность пользовательского BingSource заключается в предоставлении коллекции ProperyDescriptors для типа AClass. Они извлекаются с использованием метода TypeDescriptor.GetProperties. BindingSource также должен получить доступ к базовым элементам DataSource по индексу; это обрабатывается в индексаторе BindingSource.
Чтобы использовать этот BindingSource, создайте его экземпляр, передав ваш экземпляр IDictionary, а затем назначьте этот BindingSource свойству DataSource DataGridView.
internal class myBindingSource : BindingSource
{
private IDictionary<string, AClass> source;
private System.ComponentModel.PropertyDescriptorCollection props;
public myBindingSource(IDictionary<string, AClass> source)
{
this.source = source;
props = System.ComponentModel.TypeDescriptor.GetProperties(typeof(AClass));
this.DataSource = source;
}
public override System.ComponentModel.PropertyDescriptorCollection GetItemProperties(System.ComponentModel.PropertyDescriptor[] listAccessors)
{
return props;
}
public override object this[int index]
{
get {return this.source.Values.ElementAtOrDefault(index);}
set {}
}
public override bool AllowNew
{
get { return false; }
set{}
}
public override bool AllowEdit
{
get { return false; }
}
public override bool AllowRemove
{
get {return false;}
}
public override int Count
{
get {return ((this.source == null) ? -1 : this.source.Count);}
}
}
Редактировать: я добавил переопределение свойства Count в код, чтобы метод BindingSource.ResetBindings работал правильно при вызове, чтобы заставить связанный элемент управления повторно считывать значения из BindingSource. Я также обновил код индексатора.
Если вы измените базовый источник данных пользовательского BindingSource после назначения его в качестве источника данных DataGridView, вам потребуется вызвать метод BindingSource.ResetBindings, чтобы эти изменения были отражены в сетке.
Например:
private IDictionary<string, AClass> aList;
private myBindingSource bs;
public Form1()
{
InitializeComponent();
aList = new Dictionary<string, AClass>();
bs = new myBindingSource(aList);
dgv.DataSource = bs;
aList.Add("1", new AClass());
aList.Add("2", new AClass { data1 = "AA", data2 = "BB" });
bs.ResetBindings(false);
}