Установка режимов заполнения для столбцов элемента управления DataGridView в Windows Forms
Обновлен: Ноябрь 2007
В режиме заполнения столбца элемент управления DataGridView автоматически меняет ширину столбцов таким образом, чтобы они заполняли всю имеющуюся область отображения. Элемент управления отображает горизонтальную полосу прокрутки только в том случае, если необходимо, чтобы ширина каждого столбца была не меньше значения, заданного для свойства MinimumWidth.
Изменение размера каждого столбца зависит от его свойства InheritedAutoSizeMode. Значение этого свойства наследуется от свойства AutoSizeMode столбца или свойства AutoSizeColumnsMode элемента управления, если значение столбца равно NotSet (значение по умолчанию).
Каждый столбец имеет свой режим определения размера, но вся ширина области отображения, не занятая другими столбцами, будет распределена между столбцами, для которых установлен режим Fill. Эта ширина распределяется между столбцами с заполнением пропорционально значениям их свойств FillWeight. Например, если два столбца имеют значения свойства FillWeight 100 и 200 соответственно, то ширина первого столбца будет в два раза меньше ширины второго.
Изменение размера пользователем в режиме заполнения
В отличие от режимов определения размера, основанных на содержимом ячеек, в режиме заполнения пользователь может менять размер столбцов, свойство Resizable которых имеет значение true. При изменении пользователем размера столбца с заполнением размер остальных столбцов с заполнением, следующих за этим столбцом (справа, если свойство RightToLeft имеет значение false; в противном случае — слева) также меняется, чтобы соответствующим образом перераспределить имеющуюся ширину области отображения. Если после столбца, ширина которого была изменена, нет столбцов с заполнением, ширина всех остальных столбцов с заполнением в элементе управления изменится, чтобы компенсировать сделанные изменения. Если в элементе управления нет столбцов с заполнением, то изменение размера игнорируется. При изменении размера столбца, находящегося не в режиме заполнения, размер всех столбцов с заполнением в элементе управления будет изменен с целью компенсации сделанных изменений.
После изменения размера столбца с заполнением значения FillWeight всех измененных столбцов будут пропорционально изменены. Например, если свойство FillWeight четырех столбцов с заполнением имеет значение 100, то уменьшение размера второго столбца в два раза изменит значения свойства FillWeight на 100, 50, 125 и 125 соответственно. Изменение размера столбца, находящегося не в режиме заполнения, не меняет значения свойства FillWeight, поскольку столбцы с заполнением просто изменят свою ширину для компенсации сделанных изменений, оставаясь в той же пропорции.
Коррекция значения FillWeight в зависимости от содержимого
Можно инициализировать значения свойства FillWeight для столбцов с заполнением, используя методы автоматического изменения размера DataGridView, например метод AutoResizeColumns. Этот метод выполняет предварительный расчет ширины столбцов, необходимой для отображения их содержимого. Затем элемент управления корректирует значения свойства FillWeight для всех столбцов с заполнением таким образом, чтобы их соотношение соответствовало соотношению рассчитанных значений ширины. Наконец, элемент управления меняет размер столбцов с заполнением в соответствии с новым соотношением значений свойства FillWeight, чтобы ширина доступного пространства по горизонтали была распределена между всеми столбцами.
Пример
Описание
Используя соответствующие значения свойств AutoSizeMode, MinimumWidth, FillWeight и Resizable, можно настроить изменение размера столбцов различными способами.
В приведенном ниже примере кода демонстрируется использование различных значений свойств AutoSizeMode, FillWeight и MinimumWidth различных столбцов. В этом примере элемент управления DataGridView связан с его собственной коллекцией Columns, а отдельный столбец связан с каждым из свойств HeaderText, AutoSizeMode, FillWeight, MinimumWidth и Width. Каждый из столбцов также представлен в элементе управления отдельной строкой, и изменение в строке влечет за собой изменение свойств соответствующего столбца. Это позволяет продемонстрировать влияние изменения значений.
Код
Imports System
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
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);
}
}
Комментарии
Порядок работы с демонстрационным приложением.
Измените размер формы. Обратите внимание, как изменяется ширина столбцов, и в то же время сохраняются пропорции, определенные с помощью значений свойства FillWeight.
Измените размеры столбцов путем перетаскивания разделителей столбцов мышью. Обратите внимание, как изменились значения свойства FillWeight.
Измените значение свойства MinimumWidth для одного из столбцов, затем перетащите границу, чтобы изменить размер формы. Обратите внимание, что при сильном уменьшении размера формы значения свойства Width не уменьшаются ниже значений свойства MinimumWidth.
Увеличьте значения свойства MinimumWidth для всех столбцов таким образом, чтобы суммарное значение было больше ширины элемента управления. Обратите внимание на появление горизонтальной полосы прокрутки.
Измените значения свойства AutoSizeMode для некоторых столбцов. Обратите внимание на то, что происходит при изменении размера столбцов или формы.
Компиляция кода
Для этого примера требуются следующие компоненты:
- Ссылки на сборки System, System.Drawing и System.Windows.Forms.
Дополнительные сведения о построении этого примера из командной строки для Visual Basic или Visual C# см. в разделе Построение из командной строки (Visual Basic) или Построение из командной строки с помощью csc.exe. Можно также построить этот пример в Visual Studio путем вставки кода в новый проект. Дополнительные сведения см. в разделах Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio и Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio и Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio.
См. также
Ссылки
DataGridView.AutoResizeColumns
DataGridView.AutoSizeColumnsMode
DataGridViewAutoSizeColumnsMode
DataGridViewColumn.InheritedAutoSizeMode
DataGridViewColumn.AutoSizeMode
DataGridViewAutoSizeColumnMode
DataGridViewColumn.MinimumWidth
Другие ресурсы
Изменение размера столбцов и строк элемента управления DataGridView в Windows Forms