DataGridView привязан к вложенному словарю

Я пробовал увидеть это: DataGridView, привязанный к словарю

Но это не совсем то, что я ищу, поэтому я здесь.

У меня есть такой словарь (просто пример того, как он выглядит):

{
    "file": 
    {
        "var-type": 
            {
                "var1": 
                       {
                           "description": "the description here",
                           "length": "the length here",
                           "type": "the type here",
                           "line": "the line number here",
                       }
            }
    }
}

И хотел бы иметь DataGridView (в реальном времени, таким образом связывая его), который выглядит следующим образом:

+------+-----------------+-----------------+---------------+
| Name |   Description   |     Length      |     Type      |
+------+-----------------+-----------------+---------------+
| var1 | the description | the length here | the type here |
+------+-----------------+-----------------+---------------+

Этот DataGridView будет в TabPage (внутри TabController, имя этой вкладки - var-type)

Сначала у меня был словарь, и каждый раз, когда пользователь хотел его DataGridView, DataGridView снова и снова создавался с нуля.

Поэтому, когда пользователь что-то меняет, он должен повторно открыть DataGridView или обновить его вручную, чтобы увидеть новые изменения. Я не хочу этого. Поэтому я попытался иметь DataTables для каждого var-type (и использовать Dictionary в качестве DataTable коллекции, и пользователь будет получать изменения в реальном времени всякий раз, когда они что-то редактируют.

Это сработало очень хорошо. Но когда дело доходит до редактирования информации о конкретной переменной, мне придется использовать .Select() (и я не могу сохранить номер строки в том же DataTable). Я бы хотел этого избежать, поэтому снова вернулся к принципу «один словарь для всех». Я также слышал, что словарь намного легче.

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

Я не хочу создавать DataGridView и использовать цикл for каждый раз, когда пользователь хочет его увидеть (поэтому я выбрал DataTables как свойства, к которым я могу получить доступ где угодно, и просто использую их как DataSource всякий раз, когда я хочу их отобразить), Я просто хочу иметь возможность использовать их, когда захочу. Это возможно?

Только для записи; да это парсер. И большое спасибо!


person Rookie    schedule 22.04.2019    source источник
comment
Да, я все время отвечаю на подобные сообщения. Похоже, у вас есть JSON, но вы не видите классов для объекта (и словаря). Я могу легко опубликовать код, чтобы превратить ваш объект LIst () в базу данных, но в настоящее время у меня недостаточно информации для выполнения задачи.   -  person jdweng    schedule 22.04.2019
comment
Это не настоящий JSON, это просто пример для удобства чтения. Это словарь. Я хочу избежать цикла for каждый раз, еще раз спасибо.   -  person Rookie    schedule 22.04.2019


Ответы (1)


Используйте одно из следующего:

            DataTable dt = new DataTable();

            Dictionary<string, DataRow> dict1 = dt.AsEnumerable()
                .GroupBy(x => x.Field<string>("Name"), y => y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

            Dictionary<string, List<DataRow>> dict2 = dt.AsEnumerable()
                .GroupBy(x => x.Field<string>("Name"), y => y)
                .ToDictionary(x => x.Key, y => y.ToList());
person jdweng    schedule 22.04.2019
comment
Привет, спасибо за ответ. Но вы, кажется, неправильно поняли, что я пытаюсь сделать. Я уже сказал, что отказался от DataTables и теперь использую универсальный словарь. Я привел пример в виде JSON того, как выглядит словарь, и как я хочу, чтобы он был в виде DataGridView. Добавляя что-то новое в словарь, я хочу изменить DataGridView в реальном времени. - person Rookie; 22.04.2019
comment
Зачем отказываться от DataTable, который более эффективен, чем получение JSON с последующим преобразованием JSON в классы? Вы всегда должны изменять DataSource DGV вместо того, чтобы пытаться изменить DGV напрямую. - person jdweng; 22.04.2019
comment
@Rookie Если вам нужны обновления реального типа, вам нужен объект, который может уведомлять об изменениях свойств. DataTable может, то же самое делают и BindingSource, и BindingList. Ваш лучший друг здесь, вероятно, DataTable, связанный с BindingSource. Кстати, вам действительно не нужен DataTable для каждого var-type, это содержимое DataRow. Вы можете добавить столбец (в DataTable, скрытый в DGV), который при необходимости действует как идентификатор / индексатор. - person Jimi; 22.04.2019
comment
... У меня нет JSON, приятель. Я говорил это пару раз. Это был только пример, источник - internal static Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, string>>>> Variables { get; set; }, я не пытаюсь напрямую изменять DGV. Я просто хочу, чтобы он обновлялся при изменении словаря. - person Rookie; 22.04.2019
comment
@Jimi: У меня все еще может быть несколько страниц вкладок с разными var-type только с одним DataTable? - person Rookie; 22.04.2019
comment
Если вы привяжете разные DGV к одному и тому же BindingSource, все они будут обновляться, когда что-то изменится. Возможно, вам иногда придется поиграть с CurrencyManager, но это все. Также обратите внимание, что при фильтрации DataTable с помощью DataView с последующим использованием DataView в качестве DataSource привязка по-прежнему активна, и все обновления работают одинаково. - person Jimi; 22.04.2019
comment
@Jimi: Вы сказали, что мне не нужны разные DataTable для каждого типа var, почему так? У каждого типа переменной есть свои переменные, и каждая переменная должна иметь Имя - Описание - Длина - Тип. - person Rookie; 22.04.2019
comment
Я смотрю на структуру, которую вы разместили. "var-type", что бы это ни было на практике, это идентификатор. Таким образом, поле, которое идентифицирует владельца записи. Вы показываете, что данные в DGV должны быть flattened (сокращены до одной записи). Мне это кажется довольно простым. Я не понимаю, какая у вас проблема. Я вижу много проблем из-за вложенного словаря. Если вы решите использовать эту структуру данных как JSON (или как JSON) и десериализацию в DataTable, все проблемы исчезнут. - person Jimi; 22.04.2019
comment
Вы говорите, что у вас есть словарь для нескольких файлов, а затем словарь 2-го уровня для каждого типа, например var-type, а затем словарь свойств третьего уровня? Вы siad: Словарь ‹строка, Словарь‹ строка, Словарь ‹строка, Словарь‹ строка, строка ›››› Переменные {get; набор; } - person jdweng; 22.04.2019
comment
@Jimi: Думаю, у нас обоих недопонимание. Не могли бы вы привести пример того, о чем вы говорите? Все, что я хочу, - это обновить DGV, который имеет словарь в качестве источника данных, когда в словарь добавляются новые ключи. Тип var, о котором вы говорите, - это страница вкладки, внутри этой страницы вкладки находится DGV этого конкретного типа var. Я не могу иметь несколько типов переменных в одном DataTable, это не словарь. Это одна таблица DataTable для каждого типа, поэтому я могу сделать эту таблицу, которую я опубликовал. - person Rookie; 22.04.2019
comment
@jdweng: эй, да. :) 4 уровня словаря вложены, все даты в одном словаре. Так же, как этот JSON, который я опубликовал - person Rookie; 22.04.2019
comment
Хотите обновить все 4 словаря или только один? - person jdweng; 22.04.2019
comment
@jdweng: только два последних уровня. Если вы посмотрите на этот JSON, я бы хотел обновить var1 и JSON внутри него. Я уже могу это сделать, но мне придется обновлять DGV вручную. Я хочу, чтобы это происходило автоматически. Так же, как когда источником данных является DataTable, это происходит автоматически. - person Rookie; 22.04.2019
comment
Вы должны заставить DGV перекрасить. Он не перерисовывается автоматически. Таким образом, хитрость заключается в том, чтобы установить источник данных в значение null, а затем вернуться к таблице, например: datagridview1.DataSource = null; datagridview1.DataSource = dt; - person jdweng; 22.04.2019
comment
@jdweng: как это сделать при изменении словаря? DGV находится в другой форме. Действительно ли DataTables - мой лучший вариант? - person Rookie; 22.04.2019
comment
Вам необходимо связаться со второй формой с DGV, используя экземпляр формы. Создайте в форме метод, который устанавливает для DataSource значение Null, а затем значение table. См. Мои два проекта формы: stackoverflow .com / questions / 34975508 / - person jdweng; 22.04.2019
comment
Хм, ладно, спасибо. Думаю, я придерживаюсь того, что сказал @Jimi, и перехожу на DataTables. Большое спасибо за ответ, @jdweng! - person Rookie; 22.04.2019
comment
Если у вас есть DGV2 в разных формах, не забудьте использовать BindingSource для привязки DataTables к DGV. Таким образом, все связанные файлы DGV будут обновлены (в реальном времени), даже если вы показываете форму как модальную [Form].ShowDialog();. - person Jimi; 22.04.2019