开发者

.NET ListView column order problem

开发者 https://www.devze.com 2022-12-19 08:13 出处:网络
I have a problem in a form, where I\'ve added columns to a .NET ListView control, in the following order:

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;
开发者_如何学JAVAthis.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.


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...


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)


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.


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:

.NET ListView column order problem

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.


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.


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.


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.


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


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.


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.


my fix:

  1. switch on AutoColumnReorder -> rebuild -> everything ok...
  2. switch off Auto... if not required


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消