Выбор вложенных аргументов из DataSource для dataGridView
Помогите определиться с концепцией. Есть структура
public partial class formMain : Form
{
List<datastruct> ds = new List<datastruct>();
}
public class datalang
{
public string en_EN { get; set; }
public string ru_RU { get; set; }
}
public class datavalue
{
public string value { get; set; }
public datalang value_lang { get; set; }
}
public class datastruct
{
public string name { get; set; }
public string name_long { get; set; }
public datalang name_lang { get; set; }
public string data_type { get; set; }
public string cur_byte { get; set; }
public string[] test { get; set; }
public List<datavalue> value { get; set; }
}
ds заполняется из json, но для понимания примера заполню так:
private void button1_Click(object sender, EventArgs e)
{
ds.Add(new datastruct() { name = "CFG1", name_long = "cgf1 long", data_type = "BINARY", cur_byte = "1",
test = new string[] { "en1", "ru1" }, name_lang = new datalang {en_EN = "en1", ru_RU = "ru1"},
value = new List<datavalue>()
{
new datavalue {value = "val1", value_lang = new datalang {en_EN = "val_en1", ru_RU = "val_ru1" } },
new datavalue {value = "val2", value_lang = new datalang {en_EN = "val_en2", ru_RU = "val_ru2" } }
} });
}
Надо вывести определённые куски на отображение\редактирование. Допустим выбрал отображение через DataGridView. И вот тут полное непонимание возможностей как это можно сделать, и можно вообще. Надо отобразить три колонки.
private void button2_Click(object sender, EventArgs e)
{
dataGridView1.AutoGenerateColumns = false;
dataGridView1.Columns.Clear();
var c_name = new DataGridViewTextBoxColumn()
{
HeaderText = "name short",
Width = 50,
DataPropertyName = "name",
Name = "name"
};
dataGridView1.Columns.Add(c_name);
dataGridView1.DataSource = ds;
}
Первая колонка отобразилась, но можно ли таким способом отобразить данные для второй колонки, если надо вывести значения конкретного языка, например ds.name_lang.ru_RU ? данные при этом должны редактироваться и сохранятся в первоисточнике. Если можно, то третья колонка для меня ещё сложней - должна содержать список ComboBox из значений конкретного языка, например ds.value.value_lang.ru_RU. кроме того мне надо оперировать текущим выбором ComboBox.
Ответы (1 шт):
Совет: пишите имена классов с большой буквы.
Вы неверно интерпретировали структуру данных. Здесь должен быть словарь, так как язык определяется в рантайме, а не при компиляции. Да и каждый раз переписывать код для поддержки нужного языка было бы неудобно.
У меня бы получилось как-то так.
public class DataValue
{
public string value { get; set; }
public Dictionary<string, string> value_lang { get; set; }
}
public class DataStruct
{
public string name { get; set; }
public string name_long { get; set; }
public Dictionary<string, string> name_lang { get; set; }
public string data_type { get; set; }
public string cur_byte { get; set; }
public string[] test { get; set; }
public List<DataValue> value { get; set; }
}
Десериализуется оно правильно. Тогда вы можете добавить в структуру еще одно свойство, которое будет доставать текст на нужном языке.
private string _lang = CultureInfo.CurrentCulture.Name; // .Replace("-", "_"); - может пригодиться здесь
public class DataStruct
{
public string name { get; set; }
public string name_long { get; set; }
public Dictionary<string, string> name_lang { get; set; }
public string data_type { get; set; }
public string cur_byte { get; set; }
public string[] test { get; set; }
public List<DataValue> value { get; set; }
public string Text
{
get => name_lang[_lang];
set => name_lang[_lang] = value;
}
}
Всё, теперь можете спокойно вязать вторую колонку к свойству Text.
По поводу вложенного свойства - вот здесь есть решение.
private void Grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewColumn column = Grid.Columns[e.ColumnIndex];
if (column.DataPropertyName.Contains("."))
{
object data = Grid.Rows[e.RowIndex].DataBoundItem;
string[] properties = column.DataPropertyName.Split('.');
for (int i = 0; i < properties.Length && data != null; i++)
data = data.GetType().GetProperty(properties[i]).GetValue(data);
Grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = data;
}
}
После чего можно бужет просто написать через точку, например для исходной структуры данных DataPropertyName = "name_lang.ru_RU". Но метод со словарем и дополнительным свойством надежнее.