DataGridView повторно воссоздает столбцы - PullRequest
4 голосов
/ 20 апреля 2009

У меня проблема при назначении свойства DataSource для элемента управления DataGridView. Мой DataSource - это DataTable DefaultView, и, как и ожидалось, столбцы автоматически создаются в DataGridView, чтобы соответствовать столбцам DataTable при его назначении.

Что происходит дальше, так это то, что столбцы автоматически удаляются и воссоздаются еще 2 раза DataGridView. Почему это случилось?

В конструкторе формы:

//A DataTable is created with 5 columns
//The DataTable is populated with some rows.

myDgv.AutoGenerateColumns = true;
myDgv.DataSource = myDataTable.DefaultView;
// myDgv.ColumnAdded event is fired 5 times.
// WHY: myDgv.ColumnRemoved event is fired 5 times.
// WHY: myDgv.ColumnAdded event is fired 5 times.
// WHY: myDgv.ColumnRemoved event is fired 5 times.
// WHY: myDgv.ColumnAdded event is fired 5 times.

Редактировать: Добавлен (надеюсь) автономный пример. Если я устанавливаю точки останова в обработчиках событий, я нажимаю «Добавлено» 6 раз, а «Удалено» 4 раза. DataTable содержит 2 столбца, и я никогда не требую удаления каких-либо столбцов в моем коде.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace asdasdgf
{
    public class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            DataTable dt = new DataTable();
            dt.Columns.Add("Col1", typeof(int));
            dt.Columns.Add("Col2", typeof(string));

            foreach (int i in Enumerable.Range(0, 10))
            {
                var row = dt.NewRow();
                row["Col1"] = i;
                row["Col2"] = "stackoverflow";
                dt.Rows.Add(row);
            }

            dataGridView1.ColumnAdded += new DataGridViewColumnEventHandler(dataGridView1_ColumnAdded);
            dataGridView1.ColumnRemoved += new DataGridViewColumnEventHandler(dataGridView1_ColumnRemoved);

            dataGridView1.DataSource = dt.DefaultView;
        }

        void dataGridView1_ColumnRemoved(object sender, DataGridViewColumnEventArgs e)
        {
            // Break here
        }

        void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
        {
            // Break here
        }

        // Form1.Designer.cs contents:
        #region Windows Form Designer generated code
        private System.ComponentModel.IContainer components = null;
        private System.Windows.Forms.DataGridView dataGridView1;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }



        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(12, 41);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(240, 150);
            this.dataGridView1.TabIndex = 0;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 264);
            this.Controls.Add(this.dataGridView1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion
    }
}

Ответы [ 5 ]

2 голосов
/ 20 апреля 2009

У меня есть приложение, которое использует DataGridView для отображения содержимого DataTable, но я связываю их так:

dataGridView.DataSource = dataTable;

Можете ли вы попробовать это?

EDIT:

У меня также есть следующее в автоматически сгенерированном коде:

this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;

Не уверен, почему это будет иметь значение.

1 голос
/ 21 марта 2012

У меня есть решение! Выберите форму или пользовательский элемент управления и измените значение свойства Localizable на true. Отредактируйте файл resx и исключите записи UserAddedColumn. Затем выберите вашу сетку данных и выберите «Изменить столбцы». Подавить все столбцы, которые были добавлены автоматически. Сбросить значение Localizable на false. При этом автоматически добавленные столбцы никогда не возвращались в мою сетку.

Возможно, вам нужно сохранить форму / пользовательский элемент управления и закрыть вкладку дизайна между каждой операцией.

1 голос
/ 24 апреля 2009

После долгих раздумий, похоже, это путь.

В обработчике событий Load вашей формы:

dgv.AutoGenerateColumns = false;
dgv.DataSource = myDataSource;

В обработчике событий Shown вашей формы:

dgv.AutoGenerateColumns = true;

Дает желаемый результат события ColumnAdded, которое вызывается один раз для каждого столбца, а событие ColumnRemoved не запускается вообще. (Если в обработчике события Load установлен параметр AutoGenerateColumns = true, это будет раздражать танец Add-Remove-Add.)

1 голос
/ 20 апреля 2009

Несколько месяцев назад на работе мы создавали Grid-элемент управления, который имел бы встроенные возможности фильтрации (аналогично Excel). Первоначально мы использовали datagridview и построили вокруг этого. Этот вопрос, который вы сейчас обсуждаете, стал самым большим занятием на нашей стороне! Поскольку мы использовали DGV внизу и подключались к его событиям, чтобы вызывать различные вещи, которые нам нужно было сделать, это был абсолютный кошмар. DGV - отличный контроль, но под прикрытием он делает некоторые шокирующие ш ** Лучшим обходным решением в конце дня было автоматическое создание столбцов самостоятельно. Да, это была боль, но по крайней мере мы имели полный контроль.

В нашей финальной версии мы закончили с этим все вместе и пошли по пути наследования. Мы унаследовали от DGV, и это сделало нашу жизнь намного проще. Теперь я не уверен, что вы пытаетесь достичь здесь, но если вы строите свою собственную сетку, попробуйте сначала наследование! Что касается ответа на ваш вопрос, вы не делаете ничего плохого. Datagridview просто так странно. Если вы не строите контроль над DGV и просто нуждаетесь в этих событиях, я говорю, старайтесь держаться подальше от добавленных / удаленных столбцов. Посмотрите, можете ли вы вместо этого использовать связывание завершено.

1 голос
/ 20 апреля 2009

Если myDgv.DataSource настроен на что-то, что объясняет хотя бы некоторые действия Add / Remove. Дито, когда столбцы уже присутствуют во время разработки.

Поэтому убедитесь, что ваша сетка пуста, а свойство DataSource очищено в конструкторе.

Дополнительно:

Я запустил пример кода и могу подтвердить его, но вы можете уменьшить (вдвое) безумие, перенеся код из конструктора в обычное событие Form_Load. В любом случае, это правильный путь, я вижу, что слишком много людей путают ctor и Load.

Но тогда еще есть 2 Добавить и 1 Удалить действия на столбец, я боюсь, что нам придется подписаться на эту неэффективность DataGrid. (Где-то в DataSource.set ())

Дополнительно 2:

Очевидно, что AutoGenerateColumns имеет значение true по умолчанию и не может быть напрямую установлено из окна свойств. Я очистил его, установив (и позже очистив) источник данных во время разработки. А затем с очищенным свойством AutoGenerateColumns

dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = dt.DefaultView;

Выводит только два события Add.

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