8

I wasn't able to find an answer anywhere about this seemingly simple topic: is it possible to align text of a single subitem in a WinForms ListView control?

If so, how?

I would like to have text in the same column aligned differently.

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Fueled
  • 8,776
  • 9
  • 29
  • 31

6 Answers6

12

example :

listView1.Columns[1].TextAlign = HorizontalAlignment.Right;

will set Column's "1" alignment to right

Novpiar Effendi
  • 307
  • 3
  • 4
10

Note: Due to a limitation of the underlying native ListView control (living in comctl32.dll), the first column cannot be aligned. It will be always aligned left. The second limitation is when you custom draw (custom draw subitems): when you enable column reordering, the text of the first column is NOT reordered correctly. I solved this limitation (would not call it a bug, because the listview supports many list styles and the internal data structure of a list view is a tree like one) by not allowing to reorder the first column, which in most cases is no problem, because you'll use some sort of key for the first column like number or something similar.

Martin.Martinsson
  • 1,894
  • 21
  • 25
  • 1
    This is only partially true. In actuality, the native ListView control simply ignores the specification of the column alignment when the first column is created. If you follow the creation of that first column by explicitly specifying an alignment, then that alignment will be respected. Create a LVCOLUMN structure, set the `mask` member to `LVCF_FMT`, and fill in the `fmt` member. Then, send a `LVM_SETCOLUMN` message to the control. – Cody Gray - on strike Mar 27 '21 at 08:06
8

The "ColumnHeader" class has a "TextAlign" property that will change the alignment for all subitems in the column. If you need something more fancy you could always use the "DrawSubItem" event and make it owner drawn.

David
  • 34,223
  • 3
  • 62
  • 80
  • Yes, I would need something more fancy, and that's what I was trying to imply by "single subitem" and "text in the same column aligned differently". I'll have a look at the "DrawSubItem" event. – Fueled Feb 19 '09 at 07:53
  • I cannot make your answer as the accepted one, because I feel my question hasn't been read properly and you did not provide any code samples. But, since it pointed me in the right direction, I voted you up. Thanks! – Fueled Feb 19 '09 at 09:04
5

For future reference, here's how I solved it:

// Make owner-drawn to be able to give different alignments to single subitems
lvResult.OwnerDraw = true;
...

// Handle DrawSubItem event
private void lvResult_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    // This is the default text alignment
    TextFormatFlags flags = TextFormatFlags.Left;

    // Align text on the right for the subitems after row 11 in the 
    // first column
    if (e.ColumnIndex == 0 && e.Item.Index > 11)
    {
        flags = TextFormatFlags.Right;
    }

    e.DrawText(flags);
}

// Handle DrawColumnHeader event
private void lvResult_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
    // Draw the column header normally
    e.DrawDefault = true;
    e.DrawBackground();
    e.DrawText();
}

It was necessary to handle the DrawColumnHeader, otherwise no text or column separators would be drawn.

Fueled
  • 8,776
  • 9
  • 29
  • 31
0

Put the ListView control on form and name it "listV1" and add and edit 4 columns. Also define one Index. Then, format column "0" without the header and with Width=0. That way column 0 will be invisible. Then you can format other columns as you wish (left, center,right) which are all visible.

ListView listV1 = new ListView();
uint Index = 0;   
string[] Split_Message = Some_Message.Split(','); // split it to comma...
ListViewItem L = new ListViewItem(""); //... to column "0" assign empty string...
L.SubItems.Add(Index.ToString() + "."); //... than fill the first fild in the row. It is number converted to string...
L.SubItems.Add(Split_Message[0]); //... then first string from buffer...
L.SubItems.Add(Split_Message[1]); //... again, second string from buffer etc. ...
listV1.Items.Add(L); //... and at the end write all of this into the first row.
Indexx++; // Next number.
0

Building on the answer by @Fueled, here's what I did to use the column header alignment:

    protected override void OnDrawSubItem( DrawListViewSubItemEventArgs e )
        {
        // Match the subitem alignment to the column header alignment
        TextFormatFlags flags = TextFormatFlags.Left;
        switch ( this.Columns[ e.ColumnIndex ].TextAlign )
            {
            case HorizontalAlignment.Right:
                flags = TextFormatFlags.Right;
                break;
            case HorizontalAlignment.Center:
                flags = TextFormatFlags.HorizontalCenter;
                break;
            }
        e.DrawText( flags );
        }
Glenn
  • 1,687
  • 15
  • 21