Modalità di riempimento di colonna nel controllo DataGridView Windows Form

Aggiornamento: novembre 2007

Nella modalità di riempimento di colonna, le colonne del controllo DataGridView vengono ridimensionate automaticamente per coprire l'intera larghezza dell'area di visualizzazione disponibile. Non viene visualizzata la barra di scorrimento orizzontale del controllo tranne quando la larghezza di ogni colonna deve essere uguale a o maggiore del valore della proprietà MinimumWidth.

La capacità di ridimensionamento di ciascuna colonna dipende dalla rispettiva proprietà InheritedAutoSizeMode. Il valore di questa proprietà è ereditato dalla proprietà AutoSizeMode della colonna o dalla proprietà AutoSizeColumnsMode del controllo, se il valore della colonna è NotSet (valore predefinito).

Ciascuna colonna può disporre di una modalità di ridimensionamento diversa, tuttavia tutte le colonne con modalità di ridimensionamento Fill condivideranno la larghezza dell'area di visualizzazione non utilizzata dalle altre colonne. Tale larghezza viene suddivisa tra le colonne in modalità di riempimento in parti proporzionali ai valori corrispondenti della proprietà FillWeight. Se ad esempio il valore della proprietà FillWeight di due colonne è rispettivamente 100 e 200, la larghezza della prima colonna sarà pari alla metà della seconda.

Diversamente dalle modalità di ridimensionamento basate sul contenuto delle celle, la modalità di riempimento non impedisce agli utenti di ridimensionare le colonne il cui valore della proprietà Resizable corrisponde a true. Quando un utente ridimensiona una colonna in modalità di riempimento, vengono ridimensionate anche tutte le colonne in tale modalità successive alla colonna ridimensionata (a destra, se RightToLeft è false; in caso contrario, a sinistra) per compensare la variazione nella larghezza disponibile. Se dopo la colonna ridimensionata non vi sono colonne in modalità di riempimento, verrà eseguito il ridimensionamento compensativo di tutte le altre colonne in tale modalità. Se nel controllo non sono disponibili altre colonne in modalità di riempimento, il ridimensionamento viene ignorato. Se viene ridimensionata una colonna che non è in modalità di riempimento, cambieranno le dimensioni di tutte le colonne in tale modalità presenti nel controllo.

Una volta ridimensionata una colonna in modalità di riempimento, vengono adattati proporzionalmente i valori della proprietà FillWeight di tutte le colonne modificate. Se ad esempio il valore della proprietà FillWeight di quattro colonne in modalità di riempimento è 100, con il ridimensionamento della seconda colonna a metà della sua larghezza originale i valori della proprietà FillWeight diventeranno rispettivamente 100, 50, 125 e 125. Il ridimensionamento di una colonna non in modalità di riempimento non produrrà alcuna variazione dei valori della proprietà FillWeight perché verrà eseguito semplicemente il ridimensionamento compensativo delle colonne in modalità di riempimento nel rispetto delle stesse proporzioni.

È possibile inizializzare i valori della proprietà FillWeight delle colonne in modalità di riempimento utilizzando i metodi di ridimensionamento automatico del controllo DataGridView, come ad esempio il metodo AutoResizeColumns. Con questo metodo vengono prima calcolate le larghezze necessarie per la visualizzazione del contenuto delle colonne, poi con il controllo vengono adattati i valori della proprietà FillWeight delle colonne in modalità di riempimento, in modo che le rispettive proporzioni corrispondano a quelle delle larghezze calcolate. Infine, le colonne in modalità di riempimento vengono ridimensionate utilizzando le nuove proporzioni della proprietà FillWeight, in modo da riempire lo spazio orizzontale disponibile con tutte le colonne del controllo.

Descrizione

Utilizzando i valori appropriati per le proprietà AutoSizeMode, MinimumWidth, FillWeight e Resizable, è possibile personalizzare il ridimensionamento delle colonne in diverse situazioni.

L'esempio di codice riportato di seguito consente di provare valori diversi per le proprietà AutoSizeMode, FillWeight e MinimumWidth di colonne diverse. In questo esempio, un controllo DataGridView è associato a un proprio insieme Columns, mentre ogni colonna è associata a ciascuna delle proprietà HeaderText, AutoSizeMode, FillWeight, MinimumWidth e Width. Ciascuna di queste colonne è rappresentata anche da una riga nel controllo. Se si modificano i valori in una riga, verranno aggiornate le proprietà della colonna corrispondente e sarà possibile osservare in che modo i valori interagiscono.

Codice

using System;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;

public class Form1 : Form
{
    [STAThread]
    public static void Main()
    {
        Application.Run(new Form1());
    }

    private DataGridView dataGridView1 = new DataGridView();

    public Form1()
    {
        dataGridView1.Dock = DockStyle.Fill;
        Controls.Add(dataGridView1);
        InitializeDataGridView();
        Width *= 2;
        Text = "Column Fill-Mode Demo";
    }

    private void InitializeDataGridView()
    {
        // Add columns to the DataGridView, binding them to the
        // specified DataGridViewColumn properties.
        AddReadOnlyColumn("HeaderText", "Column");
        AddColumn("AutoSizeMode");
        AddColumn("FillWeight");
        AddColumn("MinimumWidth");
        AddColumn("Width");

        // Bind the DataGridView to its own Columns collection.
        dataGridView1.AutoGenerateColumns = false;
        dataGridView1.DataSource = dataGridView1.Columns;

        // Configure the DataGridView so that users can manually change 
        // only the column widths, which are set to fill mode. 
        dataGridView1.AllowUserToAddRows = false;
        dataGridView1.AllowUserToDeleteRows = false;
        dataGridView1.AllowUserToResizeRows = false;
        dataGridView1.RowHeadersWidthSizeMode =
            DataGridViewRowHeadersWidthSizeMode.DisableResizing;
        dataGridView1.ColumnHeadersHeightSizeMode =
            DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
        dataGridView1.AutoSizeColumnsMode = 
            DataGridViewAutoSizeColumnsMode.Fill;

        // Configure the top left header cell as a reset button.
        dataGridView1.TopLeftHeaderCell.Value = "reset";
        dataGridView1.TopLeftHeaderCell.Style.ForeColor =
            System.Drawing.Color.Blue;

        // Add handlers to DataGridView events.
        dataGridView1.CellClick +=
            new DataGridViewCellEventHandler(dataGridView1_CellClick);
        dataGridView1.ColumnWidthChanged += new
            DataGridViewColumnEventHandler(dataGridView1_ColumnWidthChanged);
        dataGridView1.CurrentCellDirtyStateChanged +=
            new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);
        dataGridView1.DataError +=
            new DataGridViewDataErrorEventHandler(dataGridView1_DataError);
        dataGridView1.CellEndEdit +=
            new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);
        dataGridView1.CellValueChanged +=
            new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
    }

    private void AddReadOnlyColumn(String dataPropertyName, String columnName)
    {
        AddColumn(typeof(DataGridViewColumn), dataPropertyName, true,
            columnName);
    }

    private void AddColumn(String dataPropertyName)
    {
        AddColumn(typeof(DataGridViewColumn), dataPropertyName, false,
            dataPropertyName);
    }

    // Adds a column to the DataGridView control, binding it to specified 
    // property of the specified type and optionally making it read-only.
    private void AddColumn(
        Type type,
        String dataPropertyName,
        Boolean readOnly,
        String columnName)
    {
        // Retrieve information about the property through reflection.
        PropertyInfo property = type.GetProperty(dataPropertyName);

        // Confirm that the property exists and is accessible.
        if (property == null) throw new ArgumentException("No accessible " +
            dataPropertyName + " property was found in the " + type.Name + " type.");

        // Confirm that the property is browsable.
        BrowsableAttribute[] browsables = (BrowsableAttribute[])
            property.GetCustomAttributes(typeof(BrowsableAttribute), false);
        if (browsables.Length > 0 && !browsables[0].Browsable)
        {
            throw new ArgumentException("The " + dataPropertyName + " property has a " +
            "Browsable(false) attribute, and therefore cannot be bound.");
        }

        // Create and initialize a column, using a combo box column for 
        // enumeration properties, a check box column for Boolean properties,
        // and a text box column otherwise.
        DataGridViewColumn column;
        Type valueType = property.PropertyType;
        if (valueType.IsEnum)
        {
            column = new DataGridViewComboBoxColumn();

            // Populate the drop-down list with the enumeration values.
            ((DataGridViewComboBoxColumn)column).DataSource
                = Enum.GetValues(valueType);
        }
        else if (valueType.Equals(typeof(Boolean)))
        {
            column = new DataGridViewCheckBoxColumn();
        }
        else
        {
            column = new DataGridViewTextBoxColumn();
        }

        // Initialize and bind the column.
        column.ValueType = valueType;
        column.Name = columnName;
        column.DataPropertyName = dataPropertyName;
        column.ReadOnly = readOnly;

        // Add the column to the control.
        dataGridView1.Columns.Add(column);
    }

    private void ResetDataGridView()
    {
        dataGridView1.CancelEdit();
        dataGridView1.Columns.Clear();
        dataGridView1.DataSource = null;
        InitializeDataGridView();
    }

    private void dataGridView1_CellClick(
        object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == -1 && e.RowIndex == -1)
        {
            ResetDataGridView();
        }
    }

    private void dataGridView1_ColumnWidthChanged(
        object sender, DataGridViewColumnEventArgs e)
    {
        // Invalidate the row corresponding to the column that changed
        // to ensure that the FillWeight and Width entries are updated.
        dataGridView1.InvalidateRow(e.Column.Index);
    }

    private void dataGridView1_CurrentCellDirtyStateChanged(
        object sender, EventArgs e)
    {
        // For combo box and check box cells, commit any value change as soon
        // as it is made rather than waiting for the focus to leave the cell.
        if (!dataGridView1.CurrentCell.OwningColumn.GetType()
            .Equals(typeof(DataGridViewTextBoxColumn)))
        {
            dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

    private void dataGridView1_DataError(
        object sender, DataGridViewDataErrorEventArgs e)
    {
        if (e.Exception == null) return;

        // If the user-specified value is invalid, cancel the change 
        // and display the error icon in the row header.
        if ((e.Context & DataGridViewDataErrorContexts.Commit) != 0 &&
            (typeof(FormatException).IsAssignableFrom(e.Exception.GetType()) ||
            typeof(ArgumentException).IsAssignableFrom(e.Exception.GetType())))
        {
            dataGridView1.Rows[e.RowIndex].ErrorText =
                "The specified value is invalid.";
            e.Cancel = true;
        }
        else
        {
            // Rethrow any exceptions that aren't related to the user input.
            e.ThrowException = true;
        }
    }

    private void dataGridView1_CellEndEdit(
        object sender, DataGridViewCellEventArgs e)
    {
        // Ensure that the error icon in the row header is hidden.
        dataGridView1.Rows[e.RowIndex].ErrorText = "";
    }

    private void dataGridView1_CellValueChanged(
        object sender, DataGridViewCellEventArgs e)
    {
        // Retrieve the property to change.
        String nameOfPropertyToChange =
            dataGridView1.Columns[e.ColumnIndex].Name;
        PropertyInfo propertyToChange =
            typeof(DataGridViewColumn).GetProperty(nameOfPropertyToChange);

        // Retrieve the column to change.
        String nameOfColumnToChange =
            (String)dataGridView1["Column", e.RowIndex].Value;
        DataGridViewColumn columnToChange =
            dataGridView1.Columns[nameOfColumnToChange];

        // Use reflection to update the value of the column property. 
        propertyToChange.SetValue(columnToChange,
            dataGridView1[nameOfPropertyToChange, e.RowIndex].Value, null);
    }

}


Commenti

Per utilizzare questa applicazione di dimostrazione:

  • Modificare le dimensioni del form. Osservare come cambia la larghezza delle colonne mentre vengono mantenute le proporzioni indicate dai valori della proprietà FillWeight.

  • Modificare le dimensioni delle colonne trascinando i rispettivi separatori con il mouse. Osservare come cambiano i valori della proprietà FillWeight.

  • Modificare il valore della proprietà MinimumWidth di una colonna, quindi trascinare la colonna per ridimensionare il form. Osservare come i valori della proprietà Width non sono inferiori a quelli della proprietà MinimumWidth anche quando le dimensioni del form sono sufficientemente ridotte.

  • Incrementare i valori della proprietà MinimumWidth di tutte le colonne in modo che la combinazione di tali valori sia superiore alla larghezza del controllo. Osservare come viene visualizzata la barra di scorrimento orizzontale.

  • Modificare i valori della proprietà AutoSizeMode di alcune colonne. Osservare l'effetto del ridimensionamento delle colonne o del form.

Aggiunte alla community

Mostra: