Udostępnij przez


Tryb wypełniania kolumn w kontrolce DataGridView formularzy systemu Windows

W trybie wypełniania kolumn kontrolka DataGridView zmienia rozmiar kolumn automatycznie, tak aby wypełniały szerokość dostępnego obszaru wyświetlania. Kontrolka nie wyświetla poziomego paska przewijania z wyjątkiem sytuacji, gdy jest to konieczne, aby zachować szerokość każdej kolumny równą lub większą niż jej wartość właściwości MinimumWidth.

Rozmiar każdej kolumny zależy od jej właściwości InheritedAutoSizeMode. Wartość tej właściwości jest dziedziczona z właściwości AutoSizeMode kolumny lub właściwości AutoSizeColumnsMode kontrolki, jeśli wartość kolumny jest NotSet (wartość domyślna).

Każda kolumna może mieć inny tryb rozmiaru, ale wszystkie kolumny z trybem rozmiaru Fill będą współdzielić szerokość obszaru wyświetlania, która nie jest używana przez inne kolumny. Ta szerokość jest podzielona między kolumny trybu wypełnienia proporcjonalnie do ich wartości właściwości FillWeight. Jeśli na przykład dwie kolumny mają FillWeight wartości 100 i 200, pierwsza kolumna będzie w połowie tak szeroka, jak druga kolumna.

Zmiana rozmiaru przez użytkownika w trybie wypełniania

W przeciwieństwie do trybów zmiany rozmiaru na podstawie zawartości komórki, tryb wypełniania nie uniemożliwia użytkownikom zmiany rozmiaru kolumn, które mają wartości właściwości Resizabletrue. Gdy użytkownik zmieni rozmiar kolumny trybu wypełnienia, wszystkie kolumny trybu wypełnienia po zmienionej kolumnie (po prawej stronie, jeśli RightToLeft jest false; w przeciwnym razie po lewej stronie) zostaną również zmienione, aby zrekompensować zmianę dostępnej szerokości. Jeśli po zmianie rozmiaru kolumny nie ma kolumn trybu wypełnienia, wszystkie inne kolumny w trybie wypełnienia w kontrolce zostaną zmienione, żeby zrekompensować. Jeśli w kontrolce nie ma żadnych innych kolumn trybu wypełnienia, zmiana rozmiaru jest ignorowana. Jeśli zmienimy rozmiar kolumny, która nie jest w trybie wypełnienia, wszystkie kolumny w trybie wypełnienia w kontrolce zmienią swoje rozmiary, aby to zrekompensować.

Po zmianie rozmiaru kolumny w trybie wypełniania, wartości FillWeight dla wszystkich zmienionych kolumn są dostosowywane proporcjonalnie. Jeśli na przykład cztery kolumny w trybie wypełnienia mają FillWeight wartości 100, zmiana rozmiaru drugiej kolumny na połowę jego oryginalnej szerokości spowoduje FillWeight wartości 100, 50, 125 i 125. Zmiana rozmiaru kolumny, która nie jest w trybie wypełniania, nie spowoduje zmiany żadnych wartości FillWeight, ponieważ kolumny trybu wypełnienia po prostu zmienią rozmiar, aby zrekompensować, zachowując te same proporcje.

Korekta wagi wypełnienia opartej na zawartości

Możesz inicjować wartości FillWeight dla kolumn w trybie wypełnienia, używając metod automatycznego zmiany rozmiaru DataGridView, takich jak metoda AutoResizeColumns. Ta metoda najpierw oblicza szerokość wymaganą przez kolumny do wyświetlenia ich zawartości. Następnie kontrolka dostosowuje wartości FillWeight dla wszystkich kolumn w trybie wypełnienia, tak aby ich proporcje odpowiadały proporcjom obliczonych szerokości. Na koniec kontrolka zmienia rozmiar kolumn trybu wypełnienia przy użyciu nowych proporcji FillWeight tak, aby wszystkie kolumny w kontrolce wypełniały dostępne miejsce w poziomie.

Przykład

Opis

Używając odpowiednich wartości dla właściwości AutoSizeMode, MinimumWidth, FillWeighti Resizable, można dostosować zachowania określania rozmiaru kolumn w wielu różnych scenariuszach.

Poniższy kod demonstracyjny umożliwia eksperymentowanie z różnymi wartościami dla AutoSizeMode, FillWeighti MinimumWidth właściwości różnych kolumn. W tym przykładzie kontrolka DataGridView jest powiązana z własną kolekcją Columns, a jedna kolumna jest powiązana z każdą z właściwości HeaderText, AutoSizeMode, FillWeight, MinimumWidthi Width. Każda kolumna jest również reprezentowana przez wiersz w kontrolce, a zmiana wartości w wierszu spowoduje zaktualizowanie właściwości odpowiedniej kolumny, aby zobaczyć, jak wartości współdziałają.

Kod

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);
    }
}
Imports System.ComponentModel
Imports System.Reflection
Imports System.Windows.Forms

Public Class Form1
    Inherits Form

    <STAThread()> _
    Public Shared Sub Main()
        Application.Run(New Form1())
    End Sub

    Private WithEvents dataGridView1 As New DataGridView()

    Public Sub New()
        dataGridView1.Dock = DockStyle.Fill
        Controls.Add(dataGridView1)
        InitializeDataGridView()
        Width = Width * 2
        Text = "Column Fill-Mode Demo"
    End Sub

    Private Sub 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

    End Sub

    Private Sub AddReadOnlyColumn(ByVal dataPropertyName As String, _
        ByVal columnName As String)

        AddColumn(GetType(DataGridViewColumn), dataPropertyName, True, _
            columnName)
    End Sub

    Private Sub AddColumn(ByVal dataPropertyName As String)
        AddColumn(GetType(DataGridViewColumn), dataPropertyName, False, _
            dataPropertyName)
    End Sub

    ' Adds a column to the DataGridView control, binding it to specified 
    ' property of the specified type and optionally making it read-only.
    Private Sub AddColumn( _
        ByVal type As Type, _
        ByVal dataPropertyName As String, _
        ByVal isReadOnly As Boolean, _
        ByVal columnName As String)

        ' Retrieve information about the property through reflection.
        Dim propertyInfo1 As PropertyInfo = type.GetProperty(dataPropertyName)

        ' Confirm that the property exists and is accessible.
        If propertyInfo1 Is Nothing Then
            Throw New ArgumentException("No accessible " & dataPropertyName & _
            " property was found in the " & type.Name & " type.")
        End If

        ' Confirm that the property is browsable.
        Dim browsables As BrowsableAttribute() = CType( _
            propertyInfo1.GetCustomAttributes(GetType(BrowsableAttribute), _
            False), BrowsableAttribute())
        If browsables.Length > 0 AndAlso Not browsables(0).Browsable Then
            Throw New ArgumentException("The " & dataPropertyName & " property has a " & _
            "Browsable(false) attribute, and therefore cannot be bound.")
        End If

        ' 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.
        Dim column As DataGridViewColumn
        Dim valueType As Type = propertyInfo1.PropertyType

        If valueType.IsEnum Then

            column = New DataGridViewComboBoxColumn()

            ' Populate the drop-down list with the enumeration values.
            CType(column, DataGridViewComboBoxColumn).DataSource = _
                [Enum].GetValues(valueType)

        ElseIf valueType.Equals(GetType(Boolean)) Then
            column = New DataGridViewCheckBoxColumn()
        Else
            column = New DataGridViewTextBoxColumn()
        End If

        ' Initialize and bind the column.
        column.ValueType = valueType
        column.Name = columnName
        column.DataPropertyName = dataPropertyName
        column.ReadOnly = isReadOnly

        ' Add the column to the control.
        dataGridView1.Columns.Add(column)

    End Sub

    Private Sub ResetDataGridView()
        dataGridView1.CancelEdit()
        dataGridView1.Columns.Clear()
        dataGridView1.DataSource = Nothing
        InitializeDataGridView()
    End Sub

    Private Sub dataGridView1_CellClick( _
        ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) _
        Handles dataGridView1.CellClick

        If e.ColumnIndex = -1 AndAlso e.RowIndex = -1 Then
            ResetDataGridView()
        End If

    End Sub

    Private Sub dataGridView1_ColumnWidthChanged( _
        ByVal sender As Object, ByVal e As DataGridViewColumnEventArgs) _
        Handles dataGridView1.ColumnWidthChanged

        ' Invalidate the row corresponding to the column that changed
        ' to ensure that the FillWeight and Width entries are updated.
        dataGridView1.InvalidateRow(e.Column.Index)

    End Sub

    Private Sub dataGridView1_CurrentCellDirtyStateChanged( _
        ByVal sender As Object, ByVal e As EventArgs) _
        Handles dataGridView1.CurrentCellDirtyStateChanged

        ' 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 Not dataGridView1.CurrentCell.OwningColumn.GetType() _
            .Equals(GetType(DataGridViewTextBoxColumn)) Then

            dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)

        End If

    End Sub

    Private Sub dataGridView1_DataError( _
        ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs) _
        Handles dataGridView1.DataError

        If e.Exception Is Nothing Then Return

        ' If the user-specified value is invalid, cancel the change 
        ' and display the error icon in the row header.
        If Not (e.Context And DataGridViewDataErrorContexts.Commit) = 0 AndAlso _
            (GetType(FormatException).IsAssignableFrom(e.Exception.GetType()) Or _
            GetType(ArgumentException).IsAssignableFrom(e.Exception.GetType())) Then

            dataGridView1.Rows(e.RowIndex).ErrorText = e.Exception.Message
            e.Cancel = True

        Else
            ' Rethrow any exceptions that aren't related to the user input.
            e.ThrowException = True
        End If

    End Sub

    Private Sub dataGridView1_CellEndEdit( _
        ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) _
        Handles dataGridView1.CellEndEdit

        ' Ensure that the error icon in the row header is hidden.
        dataGridView1.Rows(e.RowIndex).ErrorText = ""

    End Sub

    Private Sub dataGridView1_CellValueChanged( _
        ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) _
        Handles dataGridView1.CellValueChanged

        ' Ignore the change to the top-left header cell.
        If e.ColumnIndex < 0 Then Return

        ' Retrieve the property to change.
        Dim nameOfPropertyToChange As String = _
            dataGridView1.Columns(e.ColumnIndex).Name
        Dim propertyToChange As PropertyInfo = _
            GetType(DataGridViewColumn).GetProperty(nameOfPropertyToChange)

        ' Retrieve the column to change.
        Dim nameOfColumnToChange As String = _
            CStr(dataGridView1("Column", e.RowIndex).Value)
        Dim columnToChange As DataGridViewColumn = _
            dataGridView1.Columns(nameOfColumnToChange)

        ' Use reflection to update the value of the column property. 
        propertyToChange.SetValue(columnToChange, _
            dataGridView1(nameOfPropertyToChange, e.RowIndex).Value, Nothing)

    End Sub

End Class

Komentarze

Aby użyć tej demonstracyjnej aplikacji:

  • Zmień rozmiar formularza. Zobacz, jak kolumny zmieniają szerokość przy zachowaniu proporcji wskazywanych przez wartości właściwości FillWeight.

  • Zmień rozmiary kolumn, przeciągając przegrody kolumn myszą. Zobacz, jak zmieniają się wartości FillWeight.

  • Zmień wartość MinimumWidth dla jednej kolumny, a następnie przeciągnij, aby zmienić rozmiar formularza. Zobacz, jak po wystarczającym zmniejszeniu formularza wartości Width nie są niższe od wartości MinimumWidth.

  • Zmień wartości MinimumWidth dla wszystkich kolumn na duże liczby, aby łączne wartości przekroczyły szerokość kontrolki. Obserwuj, jak pojawia się poziomy pasek przewijania.

  • Zmień wartości AutoSizeMode dla niektórych kolumn. Obserwuj efekt zmiany rozmiaru kolumn lub formularza.

Kompilowanie kodu

Ten przykład wymaga:

  • Odwołania do zestawów System, System.Drawing i System.Windows.Forms.

Zobacz także