Поменять местами столбцы в стандартном ListView

            System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem(new string[] {
            "1",
            "2"}, -1);
            this.listView1 = new System.Windows.Forms.ListView();
            this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.SuspendLayout();
            // 
            // listView1
            // 
            this.listView1.AllowColumnReorder = true;
            this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.columnHeader1,
            this.columnHeader2});
            this.listView1.FullRowSelect = true;
            this.listView1.HideSelection = false;
            this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
            listViewItem1});
            this.listView1.Location = new System.Drawing.Point(245, 100);
            this.listView1.MultiSelect = false;
            this.listView1.Name = "listView1";
            this.listView1.OwnerDraw = true;
            this.listView1.Size = new System.Drawing.Size(319, 184);
            this.listView1.TabIndex = 0;
            this.listView1.UseCompatibleStateImageBehavior = false;
            this.listView1.View = System.Windows.Forms.View.Details;
            this.listView1.DrawSubItem += new System.Windows.Forms.DrawListViewSubItemEventHandler(this.listView1_DrawSubItem);
        private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            string t = listView1.Items[e.ItemIndex].SubItems[e.ColumnIndex].Text;
            e.Graphics.DrawString(t, listView1.Font, Brushes.Red, e.Bounds);
        }

Столбцы перемещаются посредством изменения свойства displayIndex, либо мышкой (не знаю, как ещё можно).
Без ownerDraw работает. А с ним, заголовок первого столбца перемещается, но информация остаётся слева. Кроме того, информация второго столбца рисуется поверх той, что в первом.

А при ручном перемещении (мышкой) как этот метод вызовется? :thinking:

Во-первых, там может быть событие:

Это не тот класс,
но можно ещё поискать:

Чёт не помогает :thinking:

        private void listView1_ColumnReordered(object sender, ColumnReorderedEventArgs e)
        {
            System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder();
            messageBoxCS.AppendFormat("{0} = {1}", "OldDisplayIndex", e.OldDisplayIndex);
            messageBoxCS.AppendLine();
            messageBoxCS.AppendFormat("{0} = {1}", "NewDisplayIndex", e.NewDisplayIndex);
            messageBoxCS.AppendLine();
            messageBoxCS.AppendFormat("{0} = {1}", "Header", e.Header);
            messageBoxCS.AppendLine();
            messageBoxCS.AppendFormat("{0} = {1}", "Cancel", e.Cancel);
            messageBoxCS.AppendLine();
            System.Diagnostics.Debug.WriteLine(messageBoxCS.ToString());
            SwapSubItems(listView1, e.OldDisplayIndex, e.NewDisplayIndex);
        }

        public static void SwapSubItems(ListView listView, int fromIndex, int toIndex)
        {
            if (fromIndex == toIndex) { return; }

            if (fromIndex > toIndex)
            {
                int h = fromIndex;
                fromIndex = toIndex;
                toIndex = h;
            }

            listView.BeginUpdate();

            try
            {
                foreach (ListViewItem line in listView.Items)
                {
                    var subItem = line.SubItems[fromIndex];
                    line.SubItems.RemoveAt(fromIndex);
                    line.SubItems.Insert(toIndex, subItem);

                    if (listView.Columns.Count > toIndex)
                    {
                        var column = listView.Columns[fromIndex];
                        listView.Columns.RemoveAt(fromIndex);
                        listView.Columns.Insert(toIndex, column);
                    }
                }
            }
            finally
            {
                listView.EndUpdate();
            }
        }

Второй столбец рендерится поверх первого.
А если отключить AllowColunmReorder, то они вообще не таскаются.

А попросить перерисовать весь контрол целиком ты пробовал?

Так?

        private void listView1_ColumnReordered(object sender, ColumnReorderedEventArgs e)
        {
            Invalidate();
            listView1.Refresh();
        }

Сейчас попробовал - не помогает.
Если смотреть в дебаггере, то при перерисовке у первых двух саб-айтемов свойство e.Bounds.X равно 0.
А содержимое нулевого столбца, куда бы его ни переместить, всегда рендерится по координате x == 0.

Если смотреть в дебаггере, то при перерисовке у первых двух саб-айтемов свойство e.Bounds.X равно 0.
А содержимое нулевого столбца, куда бы его ни переместить, всегда рендерится по координате x == 0.

Я не очень понял, что ты здесь написал, попробуй переформулировать. Например почему содержимое нулевого столбца не должно рендерится по координате 0 (локальная же по отношению к контролу координата, так и должно быть).

Ещё ты в твоём примере инвалидируешь форму (лишнее действие?).
И не переставляешь сабитемы.

Ну смотри. Есть первый столбец (у которого ID == 0). Перемещаем его, скажем, на 5е место. Свойство DisplayIndex становится равно 4. Но его содержимое всё-равно рендерится там, где он был до перемещения. То есть, у левого края контрола.

Ты сказал - попробуй запросить полную перерисовку. Вот я и запросил :man_shrugging:

А как их переставлять? :thinking: Контрол же сам их переставляет при перемещении столбцов.
Тот код, который ты скидывал, я пробовал. Не помогает. Визуально вообще ничего не меняется.

  • Я предполагаю, что контрол не переставляет сабитемы при перемещении заголовков столбцов
  • Ты не написал, что ты пробовал код перестановки сабитемов внутри обработчика события с последующией полной инвалидацией контрола (а не формы).
  • Слова, которые ты говоришь о командах Invalidate и Refresh на другом объекте, говорят о том, что с инвалидацией ты не разобрался.

Какой код перерисовки? :thinking: Инвалидация это ведь и есть перерисовка.

А с чем там нужно разобраться? Вызываешь метод Invalidate() и контрол перерисовывается. Разве нет?