Question

How can i remove sorting glyph from column headers in DataGridView without removing its sorting functionality.

I am working on windows form application in C#, i want to generate report from a datagridview, where datagridview column width will assign in report column, where as the DataGridView column include the with of sorting glyph, that is unnecessary space in my case, i want to exclude it from ColumnHeader.

Était-ce utile?

La solution

This is actually quite easy to do using custom cell painting.

All you need to do is handle the DataGridView CellPainting event:

dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);

And in the handler do something like this:

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.RowIndex == -1)
    {
        e.Paint(e.CellBounds, DataGridViewPaintParts.All &~DataGridViewPaintParts.ContentBackground);

        e.Handled = true;
    }
}

The code above is very simple - just check if the current cell is in a header row (has a -1 index) then paint everything except the ContentBackground.

I've only checked this on my Windows 7 machine and it looks fine, it appears that the content background is only used for the sort glyph - you will want to test it on the target environment to make sure you don't need to do any more involved custom painting to keep the ContentBackground without the glyph.


The width of the header cell will still include the space for the glyph. I would generally accept that since changing this becomes a bit messy, but if you must have the width fit the text then something like the following will work.

First set the width in the DataBindingComplete event of the DataGridView:

void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{        
    if (dataGridView1.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.AllCells)
    {
        // Loop over all the columns
        foreach (DataGridViewColumn c in dataGridView1.Columns)
        {
            // Work out the size of the header text
            Size s = TextRenderer.MeasureText(c.HeaderText, dataGridView1.Font);

            // Change the autosize mode to allow us to see if the header cell has the 
            // longest text
            c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
            if (s.Width + 10 > c.Width)
            {
                // If the header cell is longest we set the column width
                c.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                c.Width = s.Width + 10;
            }
            else
            {
                // If the header cell is not longest, reset the autosize mode
                c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            }
        }
    }
}

Once you have done that you then need to still allow the column to autosize when the cell text is longer than the header.

For that I used the CellValueChanged event:

void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    DataGridViewColumn c = dataGridView1.Columns[e.ColumnIndex];

    if (c.AutoSizeMode == DataGridViewAutoSizeColumnMode.None)
    {
        Size s = TextRenderer.MeasureText(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), dataGridView1.Font);
        if (s.Width > c.Width)
        {
            c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
        }
    }

}

Autres conseils

You can't do it in WinForms, unless you write a custom data grid view to cater for your need, which I'd say an overkill for your requirement.

UPDATE

I've created custom progress bars to buttons, to canvas controls, but didn't do a custom data grid view. That said, here's my idea of doing this...

You essentially create a new UserControl, and add a normal DataGridView to it, and remove the headers. Now add panel above the DataGridControl that 'acts' at the column headers. You'll have to handle all the events like, clicking the headers to sort, resizing them to resize the columns and call methods on the DataGridView to do the same.

If you want the effect of hiding column headers when the user scrolls down, you'll have to do it manually as well.

Sorry, I can't give you a solid starting point than this. If you're new to creating custom controls, try creating a custom button, (ex: that has an image on the left) or a progress bar, that also display the progress percentage in the middle of it. You'll get a feeling about what you can do.

If you're using WPF, I think things like this can be easily accomplished.

I hit the same problem when trying to get right aligned header text to line up with the cell content (looks silly in a row of numbers that the header text is not also fully right aligned.) I noticed in other dgv's that it was possible to squeeze out the glyph.

Anyway real simple solution, fill out the header text with leading spaces, and set the header cell wrap mode to false. example:

    dgv.Columns["Width"].HeaderText = "        Width";
    dgv["Width"].HeaderCell.Style.WrapMode = DataGridViewTriState.False;

might take a bit of playing around to get the number of leading spaces correct, but the result is pleasing. (Dunno if it works with trailing spaces, too late at night to try.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top