【问题标题】:ObjectListView cast exception (for hit testing)ObjectListView 强制转换异常(用于命中测试)
【发布时间】:2010-12-09 22:38:07
【问题描述】:

我正在使用 Grammarian 的 ObjectListView。我将旧的列表视图更改为那个,但我所做的只是填写项目。但是当应用程序启动并且我的鼠标在列表视图上时,它会立即抛出异常:

System.InvalidCastException was unhandled
  Message="Unable to cast object of type 'System.Windows.Forms.ListViewItem' to type 'BrightIdeasSoftware.OLVListItem'."
  Source="ObjectListView"

如何解决这个问题?

如果这很重要,我也会使用 Win7。

编辑:

我使用字典。看来我需要使用 SetObjects 方法而不是添加项目。

好的,这很好,但我只是使用 dict.Value 集合。我不想通过listview修改数据,只显示。所以我只有 1 列并列出所有字符串。这可能吗?

我会很感激一个小样本。

【问题讨论】:

    标签: c# .net vb.net winforms objectlistview


    【解决方案1】:

    你是对的——你应该使用SetObjects() 方法而不是添加ListViewItems。在 ObjectListView 中,永远不应该有 ListViewItems. 控件跟踪更多信息,因此需要比 ListViewItems 提供的更多信息。

    您可能想阅读网站的Getting Started 页面,尤其是Unlearn you must 部分。

    ObjectListView 确实有它的own forum,如果你想在那里提问的话。

    【讨论】:

      【解决方案2】:

      关于 Grammarian 的回答,他们没有告诉你的是这个。

      他们告诉你只需要一条线就可以激活它,但你会发现这很头疼,而且很多工作比它值得。我高度建议你坚持正常ListView,否则你会发现自己正在编写一个1000行的模型类......只需将1个字符串添加到@987654322 @。

      在您深入了解这家ObjectListView 业务之前,请先了解一下真相......

      去下载例子看看,坦白说,我觉得用普通的ListView更容易。

      【讨论】:

        【解决方案3】:

        OP的答案:

        据我了解,您使用的是值类型为字符串的字典。

        这显示了字典中的值列表,处于详细信息模式。

                // Create dictionary.. Can be done somewhere else..
                var dictionary = new Dictionary<int, string>();
                dictionary.Add(1, "Item 1");
                dictionary.Add(2, "Item 2");
        
                // You can set up the column in the designer as well.
                objectListView1.Columns.Add(new OLVColumn(title: "Items", aspect: "Value"));
                // Initially tells OLV to use the dictionary as a datasource.
                objectListView1.SetObjects(dictionary);
        
                // .....
        
        
                // Later on, you can add another item to the dictionary.
                dictionary.Add(3, "Item 3");
                // All you have to do now, is call .BuildList(), and your listview is updated.
                // shouldPreserveState can be false if you want. I want it to be true. :)
                objectListView1.BuildList(shouldPreserveState:true);
        

        这并不完全是“一行”,但是如果您确实在设计器中设置了列,那么 SetObjects() 确实是激活它的那一行。您只需要记住在字典更改时调用 BuildList。


        @ElektroStudios 的答案

        好的,所以出于某种原因,您想使用 ListViewItem 作为您的“数据容器”。正如@Grammarian 所指出的,这不是 OLV 的预期用途,但由于 ListViewItem 是一个具有属性的类,就像任何其他具有属性的类一样,这很容易做到。

        这不是“单线”,但绝对不是write a 1000 lines model class... Just to add 1 string to a ListView。注意我指定了 2 种设置列的 getter 的方法。

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
        
                // Items collection.
                // Add your list view items to this.
                // Note the fact that we have a different amount of subitems!!!
                var items = new List<ListViewItem>
                {
                    new ListViewItem(new []{"Hello", "Stack","Overflow"}), 
                    new ListViewItem(new []{"ObjectListView is pretty damn neat!"}), 
                    new ListViewItem(new []{"Pretty", "Cool"})
                };
        
                // These are set up by the WinForms Designer when I create OLV columns in the designer.
        
                // Here, I am telling each column to use a custom getter, created by the SubItemGetter method.
                // ensures the sub-items actually exist on each LVI.
                olvColumn1.AspectGetter = SubItemGetter(0); // ListViewItem's first sub-item is the same as ListViewItem.Text. :)
                olvColumn2.AspectGetter = SubItemGetter(1);
                olvColumn3.AspectGetter = SubItemGetter(2);
        
                // NOTE: I assume you know at design-time how many columns there are in your list view.
                // Set them up as I've done above, or, if you want to be fancy..
                for (int index = 0; index < objectListView1.Columns.Count; index++)
                {
                    OLVColumn column = objectListView1.AllColumns[index];
                    column.AspectGetter = SubItemGetter(index);
                }
        
                // Tells OLV to use the items collection.
                objectListView1.SetObjects(items);
        
                // Sometime later, probably somewhere else in the code...
                items.Add(new ListViewItem(new []{"I","Dont","Care","How","Many","SubItems","There","Is!"}));
                // Tell OLV to rebuild!
                objectListView1.BuildList(shouldPreserveState:true); // I'd like to preserve state, please :)
            }
        
            private AspectGetterDelegate SubItemGetter(int subItemIndex)
            {
                // This returns a method that gives OLV the string it needs to render each cell,
                // while also making sure the sub item exists.
                return rowObject =>
                {
                    // Cast the row object to a ListViewItem. This should be safe.
                    var lvi = (ListViewItem) rowObject;
                    // Make sure the index is not out of range.
                    if (lvi.SubItems.Count <= subItemIndex)
                        return null;
                    // Return what needs to be displayed!
                    return lvi.SubItems[subItemIndex].Text;
                };
            }
        }
        

        这给了我一个像这样的默认 OLV(注意分组是可配置的!)..

        【讨论】:

        • I would like to know if exist a trick to add/convert a ListViewItem into an ObjectListView in "Details" mode 对不起,但正如您所看到的,有提到字典类型,我想转换一个普通的 Listviewitem(不在 Dictionary(of ListviewItem) 中,只是一个带有子项的 ListViewItem 对象) 添加到所需的对象以将其添加到 ObjectListView,您认为您的代码可以根据我的需要进行修改吗?无论如何,谢谢。
        • 我尝试按照您的步骤操作,但是使用 ListViewItem,只是我总是失败,哦,天哪,没有办法使用“Items.Add”方法或“SetObjects”方法用一个简单的 LVI + LVI 子项?,这个控件简直就是一场噩梦。
        • 我明天再看一遍,但我一直很喜欢这个控件:)
        • 你为什么要这样做?
        • @ElektroStudios 完成 - 这是你想要的吗?
        【解决方案4】:

        我在尝试将虚拟模式下的普通 ListView 传递给 OLV 2.7 中的 ListViewPrinter 时遇到了类似的错误

        The error occurred here:
        #if !WITHOUT_OBJECTLISTVIEW
                /// <summary>
                /// Get the nth item from the given listview, which is in virtual mode.
                /// </summary>
                /// <param name="lv">The ListView in virtual mode</param>
                /// <param name="n">index of item to get</param>
                /// <returns>the item</returns>
                override protected ListViewItem GetVirtualItem(ListView lv, int n)
                {
        // Invalid Cast happens here
                    return ((VirtualObjectListView)lv).MakeListViewItem(n);
                }
        

        它与 objectlistview 一起按预期工作。除了使用 objectlistview 之外没有其他解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-05
          • 2023-03-19
          • 1970-01-01
          • 2021-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多