Windows Forms DataGridView 控制項中的資料行填入模式
在資料行填滿模式中,DataGridView 控制項會自動調整其資料行的大小,使資料行填滿可用顯示區域的寬度。 只有在必須將每個資料行的寬度保持等於或大於其 MinimumWidth 屬性值時,這個控制項才會顯示水平捲軸。
每個資料行的調整行為取決於其 InheritedAutoSizeMode 屬性。 如果資料行值為 NotSet (預設值),則這個屬性的值會從資料行的 AutoSizeMode 屬性或控制項的 AutoSizeColumnsMode 屬性繼承。
每個資料行都可以使用不同的調整模式,但是任何使用 Fill 調整模式的資料行都會共用其他資料行未使用的顯示區域寬度。 這個寬度會按照所有填滿模式資料行之 FillWeight 屬性值的相對比例來分割。 例如,如果兩個資料行的 FillWeight 值為 100 和 200,則第一個資料行寬度會是第二個資料行寬度的一半。
使用者在填滿模式中調整大小
不同於調整模式是根據儲存格內容來調整大小,填滿模式不會防止使用者調整 Resizable 屬性值為 true
的資料行大小。 當使用者調整填滿模式資料行的大小時,已調整大小之資料行後的任何填滿模式資料行 (如果 RightToLeft 為 false
,則為右側,否則為左側) 也會調整大小,以補償可用寬度的變更。 如果已調整大小的資料行後沒有填滿模式資料行,則會調整控制項中其他所有填滿模式資料行的大小進行補償。 如果控制項中沒有其他任何填滿模式資料行,則會略過調整大小。 如果已調整非填滿模式資料行的大小,則控制項中所有填滿模式資料行會變更大小進行補償。
調整填滿模式資料行的大小之後,所有已變更資料行的 FillWeight 值都會按比例調整。 例如,如果有四個填滿模式資料行的 FillWeight 值為 100,將第二個資料行的大小調整為其原始寬度的一半會使 FillWeight 值變成 100、50、125 和 125。 調整非填滿模式資料行的大小不會變更任何 FillWeight 值,因為只有在需要維持相同比例時,才會調整填滿模式資料行的大小。
根據內容調整 FillWeight
您可以使用 DataGridView 自動化調整大小方法 (例如 AutoResizeColumns 方法),來初始化填滿模式資料行的 FillWeight 值。 這個方法會先計算資料行顯示其內容所需的寬度。 接著,控制項會調整所有填滿模式資料行的 FillWeight 值,使其比例符合計算出來的寬度比例。 最後,控制項會使用新的 FillWeight 比例來調整填滿模式資料行的大小,使控制項中的所有資料行填滿可用的水平空間。
範例
描述
您可以針對許多不同的情況,使用適當的 AutoSizeMode、MinimumWidth、FillWeight 和 Resizable 屬性值來自訂資料行調整行為。
下列示範程式碼可讓您針對不同資料行的 AutoSizeMode、FillWeight 和 MinimumWidth 屬性,試驗不同的值。 在這個範例中,DataGridView 控制項會繫結至自己的 Columns 集合,而且一個資料行會繫結至每一個 HeaderText、AutoSizeMode、FillWeight、MinimumWidth 和 Width 屬性。 每個資料行也會以控制項中的一個資料列來表示,而變更資料列中的值會更新對應資料行中的屬性,以便您查看這些值的互動方式。
程式碼
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
註解
若要使用這個示範應用程式:
變更表單的大小 觀察資料行如何在維持比例 (由 FillWeight 屬性值指定) 的同時,變更其寬度。
使用滑鼠拖曳資料行分隔線來變更資料行大小。 觀察 FillWeight 值如何變更。
變更一個資料行的 MinimumWidth 值,然後以拖曳方式調整表單的大小。 觀察當表單變得很小時,Width 值如何維持在 MinimumWidth 值以上。
將所有資料行的 MinimumWidth 值變更為較大的數值,讓結合的值超過控制項的寬度。 觀察水平捲軸的顯示方式。
變更一些資料行的 AutoSizeMode 值。 當您調整資料行或表單的大小時,觀察其效果。
編譯程式碼
這個範例需要:
- System、System.Drawing 和 System.Windows.Forms 組件的參考。
另請參閱
- DataGridView
- DataGridView.AutoResizeColumns
- DataGridView.AutoSizeColumnsMode
- DataGridViewAutoSizeColumnsMode
- DataGridViewColumn
- DataGridViewColumn.InheritedAutoSizeMode
- DataGridViewColumn.AutoSizeMode
- DataGridViewAutoSizeColumnMode
- DataGridViewColumn.FillWeight
- DataGridViewColumn.MinimumWidth
- DataGridViewColumn.Width
- DataGridViewColumn.Resizable
- Control.RightToLeft
- 調整 Windows Forms DataGridView 控制項中資料行和資料列的大小
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應