Làm cách nào để bạn tự động thay đổi kích thước cột trong điều khiển DataGridView VÀ cho phép người dùng thay đổi kích thước các cột trên cùng một lưới đó?


109

Tôi đang điền điều khiển DataGridView trên Biểu mẫu Windows (C # 2.0 không phải WPF).

Mục tiêu của tôi là hiển thị lưới lấp đầy gọn gàng tất cả chiều rộng có sẵn bằng các ô - tức là không có vùng không sử dụng (màu xám đậm) ở bên phải và định kích thước từng cột một cách thích hợp theo dữ liệu mà nó chứa, nhưng cũng cho phép người dùng thay đổi kích thước bất kỳ cột nào theo ý thích của họ.

Tôi đang cố gắng đạt được điều này bằng cách đặt AutoSizeMode của mỗi cột thành DataGridViewAutoSizeColumnMode.AllCells ngoại trừ một trong các cột mà tôi đặt thành DataGridViewAutoSizeColumnMode.Fill để đảm bảo toàn bộ khu vực lưới được lấp đầy bằng dữ liệu một cách gọn gàng. (Tôi không bận tâm rằng khi người dùng cố gắng thay đổi kích thước cột này, cột này sẽ trở lại kích thước để đảm bảo không gian ngang luôn được sử dụng.)

Tuy nhiên, như tôi đã đề cập, sau khi được tải, tôi muốn cho phép người dùng thay đổi kích thước các cột cho phù hợp với yêu cầu của riêng họ - khi đặt các giá trị AutoSizeMode này cho mỗi cột, người dùng không thể thay đổi kích thước các cột đó.

Tôi đã cố gắng không đặt AutoSizeMode của tất cả các cột cho phép thay đổi kích thước NHƯNG không đặt kích thước ban đầu theo dữ liệu mà các ô chứa. Kết quả tương tự cũng xảy ra khi thay đổi AutoSizeMode của lưới trở lại "Not Set" sau khi tải dữ liệu.

Có cài đặt nào tôi đang thiếu ở đây cho phép tự động đặt độ rộng cột mặc định VÀ người dùng thay đổi kích thước hay không hoặc có kỹ thuật nào khác mà tôi phải sử dụng khi điền điều khiển DataGridView không?


không đặt nó thành "Not Set", hãy đặt nó thành "None" để thay đổi kích thước sẽ không hoàn nguyên Quay lại - đã kiểm tra cho c #, .net2.0
bh_earth0

Câu trả lời:


132

Thủ thuật này phù hợp với tôi:

grd.DataSource = DT;

//set autosize mode
grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
grd.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
grd.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

//datagrid has calculated it's widths so we can store them
for (int i = 0; i <= grd.Columns.Count - 1; i++) {
    //store autosized widths
    int colw = grd.Columns[i].Width;
    //remove autosizing
    grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    //set width to calculated by autosize
    grd.Columns[i].Width = colw;
}

Điều xảy ra ở đây là bạn đặt tự động kích thước thành bất kỳ chế độ nào bạn cần và sau đó theo từng cột, bạn lưu trữ chiều rộng mà nó có được từ tính toán tự động kích thước, xóa tự động kích thước và đặt chiều rộng thành giá trị bạn đã lưu trữ trước đó.


1
Tôi đặt mã tương tự trong một quy trình có tên AutoResizeColumnWidthsYetAllowUserResizing. Nó được gọi sau khi lưới được điền ban đầu và cả sau khi người dùng chỉnh sửa dữ liệu (nghĩa là từ sự kiện CellEndEdit của lưới).
Nhà phát triển

5
Đây là mã tuyệt vời. Cần đưa vào sự kiện 'DataGridView1_DataSourceChanged'.
user890332

1
Đối với tôi, dường như việc làm grd.Columns(i).Width = grd.Columns(i).Widthsẽ làm được điều đó. Xem tại đây .
Antonio

2
cho c # tương tự nhưng với dấu ngoặc vuông dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop

Điều này có thể đến rất muộn, nhưng bất kỳ cơ hội hay cách nào, chúng ta có thể thay đổi kích thước dựa trên nội dung của một hàng cụ thể? Giả sử, dựa trên nội dung của các ô trong Hàng đầu tiên, không phân biệt chiều rộng của các ô trong các hàng khác?
Murtuza Husain

45

Có lẽ bạn có thể gọi

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

Sau khi thiết lập nguồn dữ liệu. Nó sẽ thiết lập chiều rộng và cho phép thay đổi kích thước.

Tìm hiểu thêm về Phương pháp MSDN DataGridView.AutoResizeColumns (DataGridViewAutoSizeColumnsMode) .


2
Tôi không chắc tại sao câu trả lời này không được chú ý nhiều hơn. Sạch hơn nhiều. Mặc dù nếu bạn đang tìm cách khớp với chiều rộng nội dung ô thì DataGridViewAutoSizeColumnsMode.AllCells hoạt động tốt hơn một chút.
iwalkbarefoot

31
sử dụng giải pháp này, tôi gặp lỗi tiếp theo: "Tham số autoSizeColumnMode không hợp lệ cho thao tác này. Nó không thể là NotSet, None hoặc Fill nhưng cần chỉ ra tiêu chí định cỡ." . Tôi đã kết thúc bằng cách sử dụng dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itho

6
Sử dụng DataGridViewAutoSizeColumnMode.Fill không hoạt động vì nó bỏ qua nội dung ô khi định cỡ cột.
Stuart Helwig

Tôi đã sử dụng phương pháp này với DataGridViewAutoSizeColumnsMode.DisplayedCells. Ngoài ra, trong Trình thiết kế biểu mẫu, AutoSizeColumnsMode được đặt thành Không có. Tôi cần thực hiện lệnh gọi phương thức này trong trình xử lý sự kiện DataBindingComplete của DataGridView, để đảm bảo nó luôn kích thước đúng (lại).
Daan

7
Tôi không hiểu tất cả các phiếu ủng hộ ... Điều này hoàn toàn không hoạt động, tài liệu MSDN rất rõ ràng, làm điều này dẫn đến một ArgumentException nếu autoSizeColumnsMode có giá trị Không có hoặc Điền.
Larry

31

Phiên bản AC # của mã Miroslav Zadravec

for (int i = 0; i < dataGridView1.Columns.Count-1; i++)
{
    dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
dataGridView1.Columns[dataGridView1.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
    int colw = dataGridView1.Columns[i].Width;
    dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dataGridView1.Columns[i].Width = colw;
}

Đăng dưới dạng Wiki cộng đồng để không làm mất uy tín của người khác


15

Trong ứng dụng của tôi, tôi đã đặt

grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;

Ngoài ra, tôi đã đặt

grid.AllowUserToOrderColumns = true;
grid.AllowUserToResizeColumns = true;

Giờ đây, chiều rộng cột có thể được thay đổi và người dùng có thể sắp xếp lại các cột. Điều đó hoạt động khá tốt đối với tôi.

Có lẽ điều đó sẽ hiệu quả với bạn.


Đặt AutoSizeColumnsMode của lưới thành "Fill" dường như đặt tất cả các cột có cùng độ rộng. Có, các cột sau đó có thể thay đổi kích thước nhưng độ rộng ban đầu đều sai. Tôi có thể cần đặt độ rộng cột trong mã "theo cách thủ công".
Stuart Helwig

DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <- Mode.Fill; (bạn đã bỏ lỡ chữ s, đó là ColumsMode ở bên trái và bên phải, vì vậy dòng đó của bạn không biên dịch) Mã để lấy dữ liệu xem để tự động kích thước là rất khó chịu, vì vậy ít nhất hãy kiểm tra câu trả lời của bạn trước . Đó là dòng đầu tiên bạn đã viết và sai.
barlop

@barlop cảm ơn bạn đã trả lời. Bạn có đặc quyền chỉnh sửa câu hỏi và câu trả lời. Nếu bạn phát hiện ra lỗi trong mã của tôi, vui lòng chỉnh sửa.
Jehof

12

Sau khi thêm dữ liệu vào lưới, hãy thêm mã sau để điều chỉnh cột theo độ dài dữ liệu trong mỗi ô

dataGrid1.AutoResizeColumns();            
dataGrid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

Đây là kết quả

nhập mô tả hình ảnh ở đây


9

Chà, tôi đã làm như thế này:

dgvReport.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dgvReport.AutoResizeColumns();
dgvReport.AllowUserToResizeColumns = true;
dgvReport.AllowUserToOrderColumns = true;

theo thứ tự cụ thể đó. Các cột được thay đổi kích thước (mở rộng) VÀ người dùng có thể thay đổi kích thước các cột sau đó.


6

Nếu tôi hiểu câu hỏi một cách chính xác, sẽ có một cách dễ dàng hơn để đạt được những gì bạn cần. Gọi dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

Điều đó sẽ làm các trick. Tuy nhiên, có một khó khăn là bạn không thể chỉ cần gọi phương thức này trực tiếp sau khi điền điều khiển DataGridView của bạn. Thay vào đó, bạn sẽ phải thêm EventHandler cho sự kiện VisibleChanged và gọi phương thức trong đó.


1
Điều đó sẽ thay đổi kích thước các cột theo nội dung, nhưng sẽ không đảm bảo tất cả không gian lưới có sẵn được sử dụng. Tức là, không "lấp đầy" không gian còn lại nếu có.
Stuart Helwig

5

Một hai dòng mã đơn giản phù hợp với tôi.

dataGridView.DataSource = dataTable;
dataGridView.AutoResizeColumns();

4

Tiếp tục câu hỏi:
Có chiều rộng cột thích ứng với nội dung (với phương pháp khác nhau trên cột),
nhưng sau đó cho phép người dùng đặt chiều rộng cột ...

Phát triển từ câu trả lời của Miroslav Zadravec , đối với tôi, những gì hiệu quả ngay lập tức là sử dụng tính năng tự động column.Widthđể thiết lập ... column.Width!

foreach (DataGridViewColumn column in dataGridView.Columns)
{
    if (/*It's not your special column*/)
    {
        column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        column.Width = column.Width; //This is important, otherwise the following line will nullify your previous command
        column.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
    }
}

//Now do the same using Fill instead of AllCells for your special column

Điều này được thử nghiệm để hoạt động khi DataGridViewđã được tạo, sử dụng một thủ thuật như thế này .


Tôi thích sử dụng foreach như mã của bạn. Nó làm cho nó dễ đọc hơn khi bạn không có bất kỳ phép toán nào ở trên cùng của vòng lặp. Tôi đã làm theo cách đó và "column.Width = column.Width;" là thú vị.
Greg Barth

4

Điều này đã làm tôi kỳ diệu:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

1
Giải pháp đơn giản!
Mark Kram

1
Chỉ phù hợp với tôi nếu được đặt thành Không có gì sau đó, tức làdataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-do-new

3

Tính năng này tự động ghép nối tất cả các cột theo nội dung của chúng, lấp đầy không gian trống còn lại bằng cách kéo dài một cột được chỉ định và ngăn hành vi 'nhảy' bằng cách đặt cột cuối cùng để lấp đầy cho bất kỳ thay đổi kích thước nào trong tương lai.

// autosize all columns according to their content
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
// make column 1 (or whatever) fill the empty space
dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
// remove column 1 autosizing to prevent 'jumping' behaviour
dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
// let the last column fill the empty space when the grid or any column is resized (more natural/expected behaviour) 
dgv.Columns.GetLastColumn(DataGridViewElementStates.None, DataGridViewElementStates.None).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

Tôi biết đó là một câu trả lời cũ, nhưng tôi làm việc rất hiệu quả, ngay cả khi không biết trước số lượng cột.
Nilo Paim,

2

Mã C # gọn gàng hơn một chút từ mã của Miroslav Zadravec giả sử tất cả các cột được tự động hóa

for (int i = 0; i < dgvProblems.Columns.Count; i++)
{
    dgvProblems.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    int colw = dgvProblems.Columns[i].Width;
    dgvProblems.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dgvProblems.Columns[i].Width = colw;
}

2

Một phiên bản khác của mã Miroslav Zadravec, nhưng tự động và phổ biến hơn một chút:

    public Form1()
    {
        InitializeComponent();
        dataGridView1.DataSource = source;
        for (int i = 0; i < dataGridView1.Columns.Count - 1; i++) {
            dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        }
        dataGridView1.Columns[dataGridView1.Columns.Count].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

    }

    void Form1Shown(object sender, EventArgs e)
    {
        for ( int i = 0; i < dataGridView1.Columns.Count; i++ )
        {
            int colw = dataGridView1.Columns[i].Width;
            dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            dataGridView1.Columns[i].Width = colw;
        }
    }

Tôi đặt phần thứ hai vào sự kiện riêng biệt, bởi vì tôi điền datagridvewvào khởi tạo biểu mẫu và nếu cả hai phần đều ở đó, thì không có gì thay đổi, bởi vì có thể autosize tính toán chiều rộng sau khi datagridviewđược hiển thị, vì vậy chiều rộng vẫn được mặc định trong Form1()phương thức. Sau khi kết thúc phương pháp này, autosize thực hiện thủ thuật của nó và ngay sau đó (khi biểu mẫu được hiển thị), chúng ta có thể đặt độ rộng bằng phần thứ hai của mã (ở đây trong Form1Showntrường hợp). Điều này làm việc đối với tôi như một cái duyên.


2

Đây là một mã đơn giản cho câu trả lời của Miroslav Zadravec trong c #:

CurrentDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;
for (int i = 0; i < dataGridView1.Columns.Count; i++) dataGridView1.Columns[i].Width = dataGridView1.Columns[i].Width;
CurrentDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

1

Bạn đã cố gắng thiết lập thuộc FillWeighttính của DataGridViewColumnsđối tượng của mình chưa?

Ví dụ:

this.grid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
this.grid1.Columns[0].FillWeight = 1.5;

Tôi nghĩ rằng nó sẽ hoạt động trong trường hợp của bạn.


1

Một chút cải tiến từ phiên bản của Schnapple

int nLastColumn = dgv.Columns.Count - 1;
for (int i = 0; i < dgv.Columns.Count; i++)
{
    if (nLastColumn == i)
    {
        dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }
    else
    {
        dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    }
}

for (int i = 0; i < dgv.Columns.Count; i++)
{
    int colw = dgv.Columns[i].Width;
    dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dgv.Columns[i].Width = colw;
}


1

Chiều rộng cột được đặt để phù hợp với nội dung của nó Tôi đã sử dụng câu lệnh dưới đây, Nó đã giải quyết được vấn đề của tôi.

Bước đầu tiên :

RadGridViewName.AutoSize = true;

Bước thứ hai :

// This mode  fit in the header text and column data for all visible rows. 
this.grdSpec.MasterTemplate.BestFitColumns();

Bước thứ ba:

for (int i = 0; i < grdSpec.Columns.Count; i++) 
{
    // The column width adjusts to fit the contents all cells in the control.
    grdSpec.Columns[i].AutoSizeMode = BestFitColumnMode.AllCells; 
}

1
foreach (DataGridViewColumn c in dataGridView.Columns)
    c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);

Điều này sẽ hoạt động cho dù dataGridViewđã được hiển thị hay chưa (tức là ngay cả khi được gọi từ hàm tạo lớp).

Phương pháp tương tự nhưng DataGridViewAutoSizeColumnMode.DisplayedCellskhông thành công trong trường hợp trên vì lý do rõ ràng - chưa có ô nào được hiển thị! Vì một số lý do không rõ ràng, AutoResizeColumnscũng không thành công trong trường hợp này.


0

Ví dụ: nếu bạn liên kết nguồn dữ liệu của mình với một cơ sở dữ liệu, bạn cần đặt các thuộc tính sau khi quá trình liên kết hoàn tất:

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoResizeColumns();
            dgv.AllowUserToResizeColumns = true;
        }

0
  • Cảm ơn giải pháp ở trên (Để lặp lại DataGridView.Columns, hãy thay đổi AutoSizeModethành giá trị hợp lệ, thu thập giá trị chiều rộng và đặt lại sau khi thay đổi AutoSizeModethànhDataGridViewAutoSizeColumnMode.None ).
  • Tôi đã đấu tranh với nó và nhận thấy nó sẽ không hoạt động bất cứ khi nào nó được gọi từ hàm tạo lớp hoặc bất kỳ dòng nào trước Form.Show()hoặc Form.ShowDialog(). Vì vậy, tôi đặt đoạn mã này trong Form.Shownsự kiện và điều này phù hợp với tôi.
  • Mã đã chuyển đổi của tôi, không liên quan đến bất kỳ DataGridView.AutoSizeColumnsModebộ nào đã đặt trước đó, tôi sử dụng DataGridViewColumn.GetPreferredWidth()thay vì thay đổi DataGridViewColumn.AutoSizeModevà đặt giá trị chiều rộng ngay lập tức, sau đó thay đổi DataGridView.AutoSizeColumnsModemột lần:

    private void form_Shown(object sender, EventArgs e)
    {
            foreach (DataGridViewColumn c in dataGridView.Columns)
                c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.DisplayedCells, true);
            dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
    }
  • Hãy chắc chắn để thiết lập

            dataGridView.AllowUserToResizeColumns = true;
  • Tôi không biết làm thế nào mà điều này chỉ hoạt động sau khi biểu mẫu được hiển thị.


0

Tôi phải làm điều này trong VB và muốn tách nó ra thành một phương thức mà tôi đã đặt trong Mô-đun. Bạn có thể thêm cột Điền làm tham số ByRef khác nếu muốn.

''' <summary>
''' Makes all columns in a DataGridView autosize based on displayed cells,
''' while leaving the column widths user-adjustable.
''' </summary>
''' <param name="dgv">A DataGridView to adjust</param>
Friend Sub MakeAdjustableAutoSizedGridCols(ByRef dgv As DataGridView)
    Dim width As Integer

    For Each col As DataGridViewColumn In dgv.Columns
        col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
        width = col.Width
        col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
        col.Width = width
    Next
    dgv.AllowUserToResizeColumns = True
End Sub

0

Bạn có thể làm điều gì đó như sau:

   grd.DataSource = getDataSource();

    if (grd.ColumnCount > 1)
    {
        for (int i = 0; i < grd.ColumnCount-1; i++)
            grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;

        grd.Columns[grd.ColumnCount-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }

    if (grd.ColumnCount==1)
        grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

Tất cả các cột sẽ thích ứng với nội dung ngoại trừ cột cuối cùng sẽ lấp đầy lưới.


0

Với $ array là nội dung của PSCustomObject, điều này hoạt động:

$dataGridView1.DataSource=[collections.arraylist]($array)
$dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.