.NET ListView column order problem
Asked Answered
F

13

14

I have a problem in a form, where I've added columns to a .NET ListView control, in the following order:

A   | B   | C   | D

The display index for columns A-D is 0-3, in that order, yet they display in the wrong order:

A   | B   | D   | C
            ^-----^  these are switched at runtime

Note: Everything looks as I want it at design time.

I guess, but I don't know why, that it is because I added column C to the ListView after I had added column D. I moved it up a notch in the column editor dialog, adjusted the display indices, and checked the creation order in the .Designer.cs file, everything is in order A-D, in that order.

Yet the problem persists.

Also note: This is not just a heading label issue, the columns are swapped around, including their data. The data is added in the order I expect it to be displayed, but the last two columns are swapped.

What else do I need to check to figure out why one of my columns is in the wrong position?

I figured out the problem. For some reason the DisplayIndex property isn't persisted, even if I set it in the dialog.

If I had completely closed the form, and reopened it in Visual Studio, then it shifted around. Apparently those properties aren't detected by the dialog editor as "changed", and thus the save mechanism doesn't care to save it for me either.

The code that added the columns, was like this:

this.lvResult = new System.Windows.Forms.ListView();
this.colResultId = new System.Windows.Forms.ColumnHeader();
this.colResultTitle = new System.Windows.Forms.ColumnHeader();
this.colResultLanguage = new System.Windows.Forms.ColumnHeader();
this.colResultTags = new System.Windows.Forms.ColumnHeader();
// 
// lvResult
// 
this.lvResult.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
            | System.Windows.Forms.AnchorStyles.Left)
            | System.Windows.Forms.AnchorStyles.Right)));
this.lvResult.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colResultId,
this.colResultTitle,
this.colResultLanguage,
this.colResultTags});
this.lvResult.FullRowSelect = true;
this.lvResult.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.lvResult.HideSelection = false;
this.lvResult.Location = new System.Drawing.Point(12, 6);
this.lvResult.Name = "lvResult";
this.lvResult.Size = new System.Drawing.Size(466, 117);
this.lvResult.TabIndex = 0;
this.lvResult.UseCompatibleStateImageBehavior = false;
this.lvResult.View = System.Windows.Forms.View.Details;
this.lvResult.SelectedIndexChanged += new System.EventHandler(this.lvResult_SelectedIndexChanged);
// 
// colResultId
// 
this.colResultId.Text = "#";
this.colResultId.Width = 35;
// 
// colResultTitle
// 
this.colResultTitle.Text = "Title";
this.colResultTitle.Width = 220;
// 
// colResultTags
// 
this.colResultTags.DisplayIndex = 2;
this.colResultTags.Text = "Tags";
this.colResultTags.Width = 100;
// 
// colResultLanguage
// 
this.colResultLanguage.Text = "Language";

When I added the missing properties directly in the file, it worked.

Faustena answered 8/2, 2010 at 21:30 Comment(0)
D
6

Is it perhaps persisting something to the form's .resx instead of the .designer? I can't imagine why it'd do that, but yeah...

Maybe if all else fails, try deleting the ListView from your form. Then, create a new junk form in your project recreating the ListView on the junk form, test the junk form to make sure you're not getting the weird voodoo behavior, and then copy the ListView from the junk form back to your real form?

Terribly convoluted, I know...

Doleful answered 8/2, 2010 at 21:33 Comment(5)
Nope, the .resx file for the form is completely empty, except for the default items.Faustena
Added another suggestion...Grasping at straws. :)Doleful
I will re-add it later if I cannot figure it out, but since it isn't a showstopper problem for now, I'll keep it, hoping that I (or someone here) can help me figure it out, so that I can avoid it in the future.Faustena
I am facing this, but not sure I am not sure what is the root of the problem, what I do to solve it is: 1. Copy and paste the list view on the same form(just select the list view, ctrl+c followed by ctrl+v); 2. delete the old list view (remember the name); 3. rename the new list view with the old list view name; 4. reassigned the old list view events to new list view using properties windows. That's all. This can be done most likely in less than a minute.Valley
Thank you, william007. Your solution can be simplified. 1. Copy the listview (CTRL+C), 2. Delete the listview, 3. Paste the listview (CTRL+V). Now, the colums are in the right order at runtime.Deb
S
6

I had this problem using Visual Studio 2010. When I looked at the designer generated code, it had set the DisplayIndex for only some of the columns. At design time the columns were in the correct order but at runtime they were in a different order. When I added my columns they still had the designer generated names, e.g. ColumnHeader1, etc. When I renamed them to more meaningful names and ran my app, the runtime column ordering was correct. I looked at the designer generated code and saw that it had reordered the column creation code and had removed all the DisplayIndex values (as they were not needed)

Slight answered 25/1, 2011 at 11:58 Comment(2)
Same here. I was able to correct things by editing the designer-generated code. This is totally lame that we need to deal with this.Hervey
Same problem in VS 2015. Added new columns, but changed the order and the display indexes to what I wanted. The designer shows the correct layout, and column editor shows the correct indexes. Generated code ignores it. Solution for me was similar to what you suggest, rename a column and then the generated code loses the display indexes. The ordering is taken from the order they are stored in the array (which is correct).Pontoon
F
3

I was running into the same issue in Visual Studio 2017. At design time, they were in the right order. But at run time, the last 2 columns were switched.

What finally fixed it for me was going to the list view Tasks (the little button that shows up on the top right corner of the list view) and change the view to Large Icons. Run the project. Exit out. Go back and change the view to Details and run it. That fixed it for me.

Fukuoka answered 3/12, 2017 at 22:37 Comment(1)
The solution is actually the combination of Marie and JoseHaland
K
2

The actual behavior of the ListView Designer in Visual Studio is a little confusing. But once you understand it, it's a lot easier to work out. Here's an example:

enter image description here

The list of Members shown on the left side of the ColumnHeader Collection Editor dialog box must correspond to the order your code uses to add the SubItems. For example, here is my code:

    mImageList.Images.Add(_IconImage);
    ListViewItem Item = new ListViewItem("", mImageList.Images.Count - 1);
    Item.SubItems.Add(_ImageBase64);
    Item.SubItems.Add(_Description);
    Item.SubItems.Add(_Name);
    lvIconList.Items.Add(Item);

Note that in creating Item I am also creating the first subitem (0) which has "" as the text and is pointing at the Image I'd like displayed for it. Looking back at the Editor picture above, you can see that I've called this IconImage and given it a DisplayIndex of 0. The above code now adds the subitems in the order shown above: the base64 text, a description, and a name. In that specific order. This code and also the ordering of columns shown under Members must match up, 1:1.

Now, the DisplayIndex tells you the order these will be displayed. You can see that the first one has a DisplayIndex of 0. Looking up in that picture above, you can see that "Name" is 2nd, then "Encoded Value" as 3rd, and finally "Description is 4th in the column header. This means the DisplayIndex for "EncodedText" will be 2, as that is the position I want it to be displayed. Next, the DisplayIndex for "Description" will be 3. And the DisplayIndex for "ItemName" will be 1.

That's how this is done. You don't have to delete everything and re-start your whole coding process. All you have to do is understand what the DisplayIndex actually does.

The Members must be ordered in the same way you .Add() them in your code. You do NOT have any choice about that detail. The DisplayIndex then simply tells the ListView the ordering of those fields on the display itself.

Assuming the following function existed for my above code:

    Func<int, int> U = int idx => lvIconList.Columns.OfType<ColumnHeader>
            .Where(a => a.DisplayIndex == idx).Select(a => a.Index).Sum();

Then the headers will be displayed in this order:

    for (int i = 0; i <= lvIconList.Columns.Count - 1; i++) {
        Console.WriteLine(lvIconList.Columns(UU(i)).Text);
    }

It took a little getting-used-to.

Klina answered 7/5, 2018 at 7:6 Comment(0)
A
1

There is a way to do this, move the design time code generated for the ListView, and it's columns, then shove them into a method...see here for an example

public Mainform(){
    InitializeComponent();
    //
    InitListView();
}

public void InitListView(){
    // Design time generated code and manually add it here.
}

It's crap way of dealing with the weird design time issues....the only snag is, if you want to add another column, you will not see it at design time...

Hope this helps, Best regards, Tom.

Albers answered 8/2, 2010 at 21:45 Comment(0)
C
1

I edit the designer and write by hand for each column the DisplayIndex property. Builds fine, runs fine. Although now I see that the designer is a little bit changed, but for me it works fine.

Cromlech answered 12/12, 2015 at 7:43 Comment(0)
C
1

Bug is still there in VS 2019 (jeez). I found that simply changing one of the (Name) fields, then closing the editor with OK and then reopening the editor and changing the name back to the original fixed it.

Charwoman answered 19/3, 2021 at 21:40 Comment(0)
S
0

More than moving the members, you need to reset the DisplayIndex. Set the DisplayIndex for the C column to 3 and the DisplayIndex for the D to 4

Skylab answered 23/1, 2014 at 19:0 Comment(1)
"adjusted the display indices" - so that was already tried. I've had the same issue. It's ignoring the indexes you set, though storing them somewhere, just not in the generated code.Pontoon
C
0

To add a column to the ListView control in Visual Studio 2015 and have the columns line up correctly with their values so they are not shifted around, follow these steps:

  1. Go to the Form in Visual Studio.
  2. Click the smart tag at the top right of the ListView control. (The little arrow).
  3. Click Edit Columns.
  4. The ColumnHeader Collection Editor dialog box opens.
  5. Click the Add button.
  6. columnHeader1 will be displayed with a number beside it in the Members box.
  7. Now look at the properties box, the box beside the Members box, and look for DisplayIndex under Behavior. If DisplayIndex is not displayed, click the arrow beside Behavior to display it.
  8. The number in DisplayIndex will match the number of columnHeader1.
  9. Notice the two big, bold, black arrows between the Members box and the properties box. One is for moving up, the other for moving down.
  10. If you want to move columnHeader1 (your new column) to a different position, select it, then click either the big, bold black up arrow, or the big, bold, black down arrow to position it to where you want it to appear in your ListView control.
  11. As you move columnHeader1 up or down, the number beside it will change, but the number in the DisplayIndex will remain the same. Not Good! The columnHeader1 number must match the DisplayIndex number.
  12. Change the DisplayIndex number so it matches the number of the columnHeader1. If the number beside columnHeader1 is now 2, then change DisplayIndex to 2. Just make sure they both have the same number.
  13. Now look for Name under Design in the properties box and change the name of columnHeader1 to the name you want for your new column.
  14. Now look for Text under Misc. and change ColumnHeader to the name you want for your new column.
  15. Click OK. The new column will be positioned where you planted it with correct values under it.
Cookery answered 3/4, 2018 at 1:7 Comment(0)
W
0

Check the designer file Form.Designer.cs.

If you search up for each column name (here it's called columnName), you should see something like this:

this.columnName.DisplayIndex = 0;
this.columnName.Text = ...;
this.columnName.Width = ...;
...

For me, one of the columns didn't even set DisplayIndex, so make sure each column has set its DisplayIndex in the order you want.

Workout answered 18/7, 2022 at 19:47 Comment(0)
M
0

my fix:

  1. switch on AutoColumnReorder -> rebuild -> everything ok...
  2. switch off Auto... if not required
Molest answered 25/11, 2022 at 11:2 Comment(1)
Welcome to Stackoverflow. This question is asked more than 12 years ago and it has an accepted answer. Please add some details about the reason you are adding a new answer.Germander
S
-1

I know how to fix this, you need to Rebuild the project, it will come out nice again.

Stocktonontees answered 9/5, 2013 at 3:51 Comment(0)
L
-1

I have this issue now and then, but only when I make many changes to a project and insert columns before others in the ListView.

I find three separate fixes work, but none work all the time. However, the following has always worked for me:

  1. Move any column in the middle up then down.
  2. Rebuild the project Build>>Rebuild
  3. Close then reopen the project

I find that neither (1) nor (2) works every time, and that not doing (3) can result in the out-of-order condition to returning at next open.

Liberec answered 9/8, 2017 at 19:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.