【问题标题】:.NET ListView column order problem.NET ListView 列顺序问题
【发布时间】:2011-01-14 13:31:53
【问题描述】:

我在表单中遇到问题,我已按以下顺序将列添加到 .NET ListView 控件:

A   | B   | C   | D

A-D 列的显示索引为 0-3,按该顺序显示,但显示顺序错误:

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

注意:在设计时,一切看起来都是我想要的。

我猜,但我不知道为什么,这是因为我在添加 D 列之后将 C 列添加到 ListView。我在列编辑器对话框中将其上移了一个档次,调整了显示索引,然后检查.Designer.cs文件中的创建顺序,一切都按AD顺序,按那个顺序。

但问题仍然存在。

另请注意:这不仅仅是标题标签问题,列会被交换,包括它们的数据。数据按我希望它显示的顺序添加,但最后两列被交换了。

我还需要检查什么才能弄清楚为什么我的一个列在错误的位置?

我发现了问题所在。出于某种原因,即使我在对话框中设置了 DisplayIndex 属性,也不会保留它。

如果我完全关闭了表单,然后在 Visual Studio 中重新打开它,它就会移动。显然,对话框编辑器没有将这些属性检测为“已更改”,因此保存机制也不关心为我保存它。

添加列的代码是这样的:

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";

当我直接在文件中添加缺少的属性时,它起作用了。

【问题讨论】:

    标签: .net listview


    【解决方案1】:

    它是否可能在表单的 .resx 而不是 .designer 中保留一些东西?我无法想象为什么会这样做,但是是的......

    如果一切都失败了,请尝试从表单中删除 ListView。然后,在您的项目中创建一个新的垃圾表单,在垃圾表单上重新创建 ListView,测试垃圾表单以确保您没有得到奇怪的巫毒行为,然后将垃圾表单中的 ListView 复制回您的真实表单?

    非常复杂,我知道...

    【讨论】:

    • 不,表单的 .resx 文件完全是空的,除了默认项。
    • 添加了另一个建议...抓住稻草。 :)
    • 如果我无法弄清楚,我稍后会重新添加它,但由于现在它不是一个阻碍问题,我会保留它,希望我(或这里的人)可以提供帮助我想办法,这样我以后就可以避免了。
    • 我正面临这个问题,但不确定我不确定问题的根源是什么,我要解决的问题是: 1. 将列表视图复制并粘贴到同一个表单上(只需选择列表视图,ctrl+c 后跟 ctrl+v); 2.删除旧的列表视图(记住名字); 3.用旧的列表视图名称重命名新的列表视图; 4. 使用属性窗口将旧的列表视图事件重新分配给新的列表视图。就这样。这很可能在一分钟内完成。
    • 谢谢你,william007。您的解决方案可以简化。 1. 复制列表视图 (CTRL+C), 2. 删除列表视图, 3. 粘贴列表视图 (CTRL+V)。现在,列在运行时的顺序正确。
    【解决方案2】:

    有一种方法可以做到这一点,移动为 ListView 生成的设计时代码,以及它的列,然后将它们推入一个方法中......请参阅此处以获取示例

    公共主要形式(){ 初始化组件(); // 初始化列表视图(); } 公共无效初始化列表视图(){ // 设计时生成的代码并在此处手动添加。 }

    这是处理奇怪的设计时问题的垃圾方式......唯一的障碍是,如果你想添加另一列,你不会在设计时看到它......

    希望这会有所帮助, 最好的祝福, 汤姆。

    【讨论】:

      【解决方案3】:

      我在使用 Visual Studio 2010 时遇到了这个问题。当我查看设计器生成的代码时,它只为某些列设置了 DisplayIndex。在设计时,这些列的顺序正确,但在运行时它们的顺序不同。当我添加我的列时,他们仍然有设计师生成的名称,例如ColumnHeader1 等。当我将它们重命名为更有意义的名称并运行我的应用程序时,运行时列排序是正确的。我查看了设计器生成的代码,发现它已经重新排序了列创建代码并删除了所有 DisplayIndex 值(因为它们不需要)

      【讨论】:

      • 这里也一样。我能够通过编辑设计器生成的代码来纠正问题。这完全是蹩脚的,我们需要处理这个。
      • VS 2015 中的相同问题。添加了新列,但将顺序和显示索引更改为我想要的。设计器显示正确的布局,列编辑器显示正确的索引。生成的代码会忽略它。我的解决方案类似于您的建议,重命名一列,然后生成的代码会丢失显示索引。排序取自它们存储在数组中的顺序(这是正确的)。
      【解决方案4】:

      我知道如何解决这个问题,你需要重新构建项目,它会再次出现。

      【讨论】:

        【解决方案5】:

        除了移动成员之外,您还需要重置 DisplayIndex。 将 C 列的 DisplayIndex 设置为 3,将 D 列的 DisplayIndex 设置为 4

        【讨论】:

        • "调整了显示索引" - 所以已经尝试过了。我有同样的问题。它忽略了您设置的索引,尽管将它们存储在某个地方,而不是在生成的代码中。
        【解决方案6】:

        我编辑设计器并为每一列手写 DisplayIndex 属性。 构建良好,运行良好。虽然现在我看到设计师有点变了,但对我来说效果很好。

        【讨论】:

          【解决方案7】:

          我时不时会遇到这个问题,但只有当我对项目进行许多更改并在 ListView 中的其他列之前插入列时。

          我发现三个单独的修复程序有效,但没有一个始终有效。但是,以下内容一直对我有用:

          1. 将中间的任意一列上下移动。
          2. 重建项目 Build>>Rebuild
          3. 关闭然后重新打开项目

          我发现(1)和(2)每次都不起作用,不做(3)会导致在下次打开时返回的无序状态。

          【讨论】:

            【解决方案8】:

            我在 Visual Studio 2017 中遇到了同样的问题。在设计时,它们的顺序是正确的。但在运行时,最后 2 列被切换了。

            最终为我解决的问题是转到列表视图任务(显示在列表视图右上角的小按钮)并将视图更改为大图标。运行项目。退出。返回并将视图更改为详细信息并运行它。这为我解决了问题。

            【讨论】:

            • 解决方案其实是玛丽和何塞的结合
            【解决方案9】:

            若要在 Visual Studio 2015 中向 ListView 控件添加一列,并使列与其值正确对齐,以便它们不会四处移动,请按以下步骤操作:

            1. 转到 Visual Studio 中的表单。
            2. 单击 ListView 控件右上角的智能标记。 (小箭头)。
            3. 点击编辑列。
            4. ColumnHeader 集合编辑器对话框打开。
            5. 点击添加按钮。
            6. columnHeader1 将在成员框中显示,旁边有一个数字。
            7. 现在查看属性框,即成员框旁边的框,并在行为下查找 DisplayIndex。如果 DisplayIndex 未显示,请单击 Behavior 旁边的箭头以显示它。
            8. DisplayIndex 中的数字将与 columnHeader1 的数字匹配。
            9. 注意成员框和属性框之间的两个粗体黑色大箭头。一个向上移动,一个向下移动。
            10. 如果您想将 columnHeader1(您的新列)移动到其他位置,请选择它,然后单击黑色粗体大箭头或黑色粗体向下大箭头,将其定位到您想要的位置出现在您的 ListView 控件中。
            11. 当您向上或向下移动 columnHeader1 时,它旁边的数字会发生变化,但 DisplayIndex 中的数字将保持不变。不好! columnHeader1 编号必须与 DisplayIndex 编号匹配。
            12. 更改 DisplayIndex 编号,使其与 columnHeader1 的编号匹配。如果 columnHeader1 旁边的数字现在是 2,则将 DisplayIndex 更改为 2。只要确保它们具有相同的数字即可。
            13. 现在在属性框中的 Design 下查找 Name,并将 columnHeader1 的名称更改为您想要的新列名称。
            14. 现在在 Misc 下查找 Text。并将 ColumnHeader 更改为新列所需的名称。
            15. 单击确定。新列将放置在您种植它的位置,并在其下方显示正确的值。

            【讨论】:

              【解决方案10】:

              Visual Studio 中 ListView 设计器的实际行为有点令人困惑。但是一旦你理解了它,它就会容易得多。这是一个例子:

              ColumnHeader 集合编辑器对话框左侧显示的成员列表必须与您的代码用于添加子项的顺序相对应。例如,这是我的代码:

                  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);
              

              请注意,在创建 Item 时,我还创建了第一个子项 (0),它以“”作为文本并指向我希望为其显示的图像。回看上面的编辑器图片,你可以看到我已经调用了这个 IconImage 并给它一个 DisplayIndex 0。上面的代码现在按照上面显示的顺序添加了子项:base64 文本,描述和名称。按照那个特定的顺序。此代码以及“成员”下显示的列的顺序必须匹配,1:1。

              现在,DisplayIndex 告诉您这些将显示的顺序。你可以看到第一个的 DisplayIndex 为 0。在上面那张图中,你可以看到“Name”是 2nd,然后是“Encoded Value”是 3rd,最后是“Description 在列标题中是 4th。这个表示“EncodedText”的 DisplayIndex 将为 2,因为这是我希望它显示的位置。接下来,“Description”的 DisplayIndex 将为 3。“ItemName”的 DisplayIndex 将为 1。

              这就是这样做的。您不必删除所有内容并重新开始整个编码过程。您所要做的就是了解 DisplayIndex 的实际作用

              成员必须按照您在代码中 .Add() 的方式进行排序。你对那个细节没有任何选择。 DisplayIndex 然后简单地告诉 ListView 这些字段在显示本身上的顺序。

              假设我上面的代码存在以下函数:

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

              那么header就会按照这个顺序显示:

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

              需要一点时间来适应。

              【讨论】:

                【解决方案11】:

                在 VS 2019 中仍然存在错误(天哪)。我发现只需更改(名称)字段之一,然后单击确定关闭编辑器,然后重新打开编辑器并将名称更改回原来的名称即可修复它。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多