Почему Columns.Insert не обновляет DisplayIndex в DataGridView (C #)? - PullRequest
0 голосов
/ 23 октября 2008

Я вставляю столбец в DataGridView программно (т.е. не привязан ни к каким таблицам / базам данных) следующим образом:

int lastIndex = m_DGV.Columns.Count - 1;  // Count = 4 in this case
DataGridViewTextBoxColumn col = (DataGridViewTextBoxColumn)m_DGV.Columns[lastIndex];
m_DGV.Columns.RemoveAt(lastIndex);
m_DGV.Columns.Insert(insertIndex, col);  // insertIndex = 2

Я обнаружил, что мои столбцы визуально вышли из строя, иногда используя этот метод. Обходной путь - вручную установить свойство DisplayIndex столбца. Добавление этого кода «исправляет его», но я не понимаю, почему он так себя ведет.

Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 3
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 2
col.DisplayIndex = insertIndex;
Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 2
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 3

Кроме того, моя сетка может динамически увеличивать количество столбцов. Я хотел увеличить его по частям, чтобы каждая вставка не требовала выделения столбцов (и соответствующей инициализации). Затем каждый «новый» столбец будет добавлен путем захвата неиспользуемого столбца с конца, вставки его в желаемое положение и отображения его.

Ответы [ 3 ]

2 голосов
/ 10 декабря 2008

У меня есть пара идей.

  1. Как насчет адресации ваших столбцов уникальным именем, а не индексом в коллекции? Возможно, у них уже нет имени, но вы можете отслеживать, кто есть кто, если бы вы дали им имя, которое что-то значило.

  2. Вы можете использовать методы GetFirstColumn, GetNextColumn, GetPreviousColumn, GetLastColumn класса DataGridViewColumnCollection, которые работают с порядком отображения, а не с порядком в коллекции. Вы также можете просто перебирать коллекцию, используя цикл for и m_DGV.Columns[i], пока не найдете нужный.

  3. Создать унаследованные DataGridView и DataGridViewColumnCollection. DataGridView просто переопределяется для использования вашего нового класса коллекции. Ваш новый DataGridViewColumnCollection будет содержать метод для обращения к коллекции по индексу отображения, предположительно путем итерации по коллекции, пока вы не найдете тот, который вам нужен (см. # 2). Или вы можете сохранить словарь и обновлять его для очень большого числа столбцов.

    Я сомневаюсь в увеличении производительности хранения словаря, так как каждый раз, когда столбец перемещается, вам, по сути, приходится переписывать все это. В любом случае повторение - это O (n), и если вы не говорите об асинхронных операциях с сотнями столбцов, вы, вероятно, в порядке.

    Возможно, вы также сможете переопределить оператор this[], если он не облажает DataGridView.

Идея № 1 может быть самой простой для реализации, но не обязательно самой красивой. Идея № 2 работает, и вы можете поместить ее в функцию DataGridViewColumn GetColumnByDisplayIndex(int Index). Идея №3 хороша и, безусловно, наиболее инкапсулирована, но не совсем тривиальна.

2 голосов
/ 23 октября 2008

Я подозреваю, что это связано с тем, что порядок столбцов в DataGridView не обязательно определяет порядок отображения, хотя без явного присвоения по умолчанию порядок столбцов определяет значения свойства DisplayIndex. Вот почему существует свойство DisplayIndex, поэтому вы можете добавлять столбцы в коллекцию без выполнения вставок - вам просто нужно указать значение DisplayIndex, и для всех объектов с равным или большим DisplayIndex происходит каскадное обновление. Из вашего примера видно, что вставленный столбец также получает первое пропущенное значение DisplayIndex.

Из вопрос / ответ Я нашел:

Изменение DisplayIndex приведет к все колонны между старым DisplayIndex и новый DisplayIndex быть сдвинутым.

Как и почти во всех коллекциях (кроме LinkedLists), всегда лучше добавить в коллекцию , чем вставить в коллекцию. Поведение, которое вы видите, является отражением этого правила.

0 голосов
/ 27 октября 2008

Спасибо cfeduke за отличный совет. Я подозревал, что Insert будет медленнее, но предоставленная ссылка просвещает меня ТОЛЬКО НАМНОГО медленнее.

Это поднимает вопрос о том, как эффективно динамически вставлять и удалять столбцы в DataGridView. Похоже, что идеальным вариантом было бы добавить множество столбцов, используя Add или AddRange, а затем никогда их не удалять. Затем вы можете смоделировать удаление, установив для свойства Visible значение false. И вы можете вставить столбец, взяв невидимый столбец, установив его DisplayIndex и сделав его видимым.

Тем не менее, я подозреваю, что при таком подходе будут наземные мины, которых следует избегать. Прежде всего, вы больше не можете индексировать свои данные простым способом. То есть m_DGV.Columns[i] и m_DGV.Rows[n].Cells[i] не будут отображены должным образом. Я полагаю, вы могли бы создать карту / словарь для поддержки внешнего интуитивного отображения.

Поскольку мое приложение (как оно разработано в настоящее время) требует частой вставки и удаления столбцов, оно может стоить того. У кого-нибудь есть предложения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...