Как предотвратить автоматическое создание столбцов в конструкторе Visual Studio в DataGridView? - PullRequest
8 голосов
/ 10 февраля 2009

Я генерирую все свои столбцы в подклассах DataGridView программно. Однако Visual Studio 2008 продолжает читать мой класс конструктора (который заполняет DataTable пустым содержимым и связывает его с DataGridView) и генерирует код для столбцов в методе InitializeComponent - в параметре процесса AutoGenerateColumns в false.

Это приводит к ошибкам при компиляции во время разработки, которые могут быть решены только путем ручного перехода в код проекта и удаления всех ссылок на эти автоматически сгенерированные столбцы.

Как я могу остановить это, делая это?

Я пробовал:

  • Создание элемента управления 'Frozen'
  • Установка DataGridView экземпляра объекта protected (предложено в предыдущем посте, который ссылается на этот сайт )

Ответы [ 10 ]

5 голосов
/ 10 февраля 2009

Я видел такое поведение раньше для ComboBox со свойством Items, и это действительно расстраивает. Вот как я справился с этим с помощью ComboBox. Вы должны иметь возможность применить это к DataGridView.

Я создал «новое» свойство с именем Items и установил, что оно не будет доступно для просмотра и будет скрыто от сериализации. Под капотом он просто получает доступ к реальному свойству Items.

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ObjectCollection Items
{
    get { return ((ComboBox)this).Items; }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new object DataSource
{
    get { return ((ComboBox)this).DataSource; }
5 голосов
/ 10 февраля 2009

Похоже, вы добавляете элементы управления в конструктор. Возможно, добавьте столбцы чуть позже - возможно, что-то вроде переопределения OnParentChanged; тогда вы сможете проверить DesignMode, поэтому вы добавляете столбцы только во время выполнения (не во время проектирования).

1 голос
/ 04 октября 2010

Предложение ДжаредПара сработало для меня:

public partial class RefusjonsOppgjorGrid : DataGridView
{
    public RefusjonsOppgjorGrid()
    {
        InitializeComponent();
    }

    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new DataGridViewColumnCollection Columns
    {
        get{ return base.Columns;}
    }
}
1 голос
/ 02 сентября 2010

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

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

1 голос
/ 11 февраля 2009

Марк был прав. Дизайнер смотрит на конструктор для этого автогенерирующего поведения. Вот как я это обошел.

Взял код, который конструирует / связывает DataTable с DataGridView из конструктора и поместил его в метод.

Использование события Load в содержащей форме - которое содержит несколько DataGridView с вызовом метода BindData() для каждого экземпляра


List<Control> childControls = Misc.Misc.GetAllChildControls(this);
foreach (Control ctrl in childControls) {
    if (ctrl is WorksheetGridView) {
         WorksheetGridView wsgv = ctrl as WorksheetGridView;
         wsgv.BindData();
    }
}

, где GetAllChildControls - метод в классе помощника

<code>
internal static List<Control> GetAllChildControls(Control topControl)
{
    List<Control> ctrlStore = new List<Control>();
    ctrlStore.Add(topControl);
    if (topControl.HasChildren)
    {
        foreach (Control ctrl in topControl.Controls)
        {
            ctrlStore.AddRange(GetAllChildControls(ctrl));                }
        }
    }
    return ctrlStore;
}

Извините, если это явно, но я никогда не хочу забывать, как это сделать!

0 голосов
/ 30 июня 2017

Снова откройте форму в конструкторе, чтобы столбцы были сгенерированы автоматически, затем щелкните DataGridView, выберите «Редактировать столбцы», просмотрите каждый столбец с ошибками и установите для свойства «Видимый» значение «Ложь». Сохраните и закройте / повторно откройте форму, чтобы убедиться, что это больше не происходит. Это было единственное решение для некодирования, которое действительно работало для меня, и я не хотел добавлять код для решения проблемы дизайнера winforms.

0 голосов
/ 09 мая 2016

Поскольку этот вопрос все еще остается вопросом для некоторых, в том числе для меня, еще несколько дней назад, я решил опубликовать свое решение, и то, которое я преподаю учащимся в моих классах, начиная с этого момента:

Сначала я создаю объект DataGridView (DGV) и создаю столбцы в режиме конструктора, принимая к сведению имя объекта для конкретного столбца.

Теперь, когда я хочу связать данные из моей базы данных (SQL Server, для этого кода). Я изменяю объекты столбца и привязываю каждый столбец непосредственно к данным из DataTable.

private void FillAddresses()
    {
        // erase any old data
        if (AddrTable != null)
            AddrTable.Clear();
        else
            AddrTable = new DataTable();

        // switch-case for panel types that need an address
        switch(PanelType)
        {
            case "Customer":
            case "Customers":
            case "Location":
            case "Locations":
            case "Employee":
            case "Employees":
                BuildStateColumnChoices();
                SqlCommand sqlAddrCmd = new SqlCommand();
                sqlAddrCmd.CommandText = "exec SecSchema.sp_GetAddress " + PanelType +
                    "," + ObjectID.ToString(); // Fill the DataTable with a stored procedure
                sqlAddrCmd.Connection = DBConnection;
                sqlAddrCmd.CommandType = CommandType.Text;
                SqlDataAdapter sqlDA = new SqlDataAdapter(sqlAddrCmd);

                try
                {
                    sqlDA.Fill(AddrTable);

                    dgvAddresses.AutoGenerateColumns = false;
                    // Actually, you set both the DataSource and DataPropertyName properties to bind the data
                    dgvAddresses.DataSource = AddrTable;

                    // Note that the column parameters are using the name of the object from the designer.
                    // This differs from the column names.
                    // The DataProperty name is set to the column name returned from the Stored Procedure
                    dgvAddresses.Columns["colAddrType"].DataPropertyName = "Type";
                    dgvAddresses.Columns["collAddress"].DataPropertyName = "Address";
                    dgvAddresses.Columns["colAptNum"].DataPropertyName = "Apt#";
                    dgvAddresses.Columns["colCity"].DataPropertyName = "city";
                    dgvAddresses.Columns["colState"].DataPropertyName = "State";
                    dgvAddresses.Columns["colZIP"].DataPropertyName = "ZIP Code";

                }
                catch(Exception errUnk)
                {
                    MessageBox.Show("Failed to load address data for panel type " +
                        PanelType + "..." + errUnk.Message, "Address error",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }

                break;
        }
    }

Для приведенного выше кода DBConnection является открытым свойством для объекта, из которого я взял этот код, в котором хранится объект SqlConnection. Кроме того, colAddressType был столбцом ComboBox. Данные из привязанного DataTable могут соответствовать только сведениям, перечисленным в ComboBox. Аналогично, colState является столбцом ComboBox, но значения по умолчанию для этого поля добавляются путем запроса другой таблицы, содержащей все состояния (в США, например, для этого примера).

Суть в том, что вы можете связать данные, которые вы хотите включить в DGV, создавая столбцы во время разработки, а затем связывая ваши данные из таблицы DataTable непосредственно со столбцами. Это позволяет вам иметь любой тип столбца, который вы хотите, а не просто TextColumn по умолчанию, который предоставляется вам механизмом привязки по умолчанию.

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

0 голосов
/ 09 августа 2015

@ ответ JaredPar дал мне большую часть решения этой проблемы, но любые элементы управления, которые содержали мой подкласс DataGridView, добавляли столбцы всякий раз, когда что-либо в конструкторе изменялось.

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

using System.Windows.Forms.Design;

[Designer(typeof(ControlDesigner))]
public class SpecificDataGridView : DataGridView
{
    [Browsable(false),
     DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new DataGridViewColumnCollection Columns
    {
        get { return base.Columns; }
    }

    ...etc...
}

Это означает, что дизайнеры не могут использовать «Редактировать элементы» и др. В задачах DataGridViewDesigner, и они не могут корректировать свойства столбцов, если хотят, но для моих нужд это было не особенно полезно. так что без потерь.

Во всяком случае, это решило проблему, и это все еще означало, что столбцы были видны в конструкторе, что было моей главной целью здесь.

Просто думал, что поделюсь.

0 голосов
/ 28 августа 2014

Это старые вопросы сейчас, но это все еще проблема в 2014 году с VS2013.

У меня был DataGridView с DataSource, установленным на BindingSource, который в свою очередь имел BindingSource в качестве DataSource. Чтобы решить мою проблему, мне не нужно было ничего менять, кроме перемещения назначения DataGridView.DataSource в переопределение OnControlCreate в форме.

0 голосов
/ 10 февраля 2009

Я часто делаю это в своих пользовательских элементах управления, если вы помещаете код, который не хотите выполнять в конструкторе, в проверку DesignMode, это должно исправить ваши проблемы.

    if (!DesignMode)
    {
        // Your code here
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...