Windows Forms DataGridView 컨트롤의 열 채우기 모드
업데이트: 2007년 11월
열 채우기 모드에서 DataGridView 컨트롤은 열의 크기를 자동으로 조정하여 사용할 수 있는 표시 영역의 너비를 채웁니다. 이 컨트롤은 모든 열의 너비를 컨트롤의 MinimumWidth 속성 값보다 크거나 같게 유지해야 하는 경우에만 가로 스크롤 막대를 표시합니다.
각 열의 크기 조정 동작은 InheritedAutoSizeMode 속성에 따라 결정됩니다. 이 속성의 값은 열의 AutoSizeMode 속성에서 상속되며, 열 값이 NotSet(기본값)인 경우에는 컨트롤의 AutoSizeColumnsMode 속성에서 상속됩니다.
각 열은 각기 다른 크기 모드를 가질 수 있지만 크기 모드가 Fill인 모든 열은 다른 열에서는 사용하지 않는 표시 영역 너비를 공유합니다. 이 너비는 채우기 모드 열의 FillWeight 속성 값 비율에 따라 해당 열에 할당됩니다. 예를 들어, FillWeight 값이 100과 200인 두 개의 열이 있는 경우 두 번째 열의 너비는 첫 번째 열의 너비의 두 배가 됩니다.
채우기 모드에서 사용자 크기 조정
셀 내용에 따라 크기를 조정하는 크기 조정 모드와는 달리 채우기 모드에서는 사용자가 Resizable 속성 값이 true인 열의 크기를 조정할 수 없습니다. 사용자가 채우기 모드 열의 크기를 조정할 경우 크기가 조정된 열 이후(RightToLeft가 false인 경우에는 오른쪽, 그렇지 않은 경우에는 왼쪽)의 모든 채우기 모드 열은 사용할 수 있는 너비 내에서 자동으로 크기가 조정됩니다. 크기가 조정된 열 이후에 채우기 모드 열이 없는 경우에는 컨트롤에 있는 다른 모든 채우기 모드 열의 크기가 알맞게 조정됩니다. 컨트롤에 다른 채우기 모드 열이 없으면 크기 조정이 무시됩니다. 채우기 모드에 있지 않은 열의 크기를 조정하면 컨트롤에 있는 모든 채우기 모드 열의 크기가 알맞게 조정됩니다.
채우기 모드 열의 크기를 조정한 후 변경된 모든 열의 FillWeight 값은 비율에 따라 조정됩니다. 예를 들어, FillWeight 값이 100인 채우기 모드 열이 네 개가 있을 때 두 번째 열의 크기를 원래 너비의 반으로 줄이면 FillWeight 값이 100, 50, 125 및 125로 변경됩니다. 채우기 모드에 있지 않은 열의 크기를 조정하는 경우에는 채우기 모드 열의 크기가 동일한 비율로 조정되므로 FillWeight 값은 변경되지 않습니다.
내용 기반 FillWeight 조정
AutoResizeColumns 메서드와 같은 DataGridView 자동 크기 조정 메서드를 사용하여 채우기 모드 열의 FillWeight 값을 초기화할 수 있습니다. 이 메서드는 먼저 열에서 내용을 표시하는 데 필요한 너비를 계산합니다. 그런 다음 해당 컨트롤은 모든 채우기 모드 열의 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에서 코드를 새 프로젝트에 붙여넣어 이 예제를 빌드할 수도 있습니다.
참고 항목
참조
DataGridView.AutoResizeColumns
DataGridView.AutoSizeColumnsMode
DataGridViewAutoSizeColumnsMode
DataGridViewColumn.InheritedAutoSizeMode
DataGridViewColumn.AutoSizeMode
DataGridViewAutoSizeColumnMode
DataGridViewColumn.MinimumWidth