5

我正在使用 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 列并列出所有字符串。这可能吗?

我会很感激一个小样本。

4

4 回答 4

3

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

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

ObjectListView 确实有自己的论坛,如果您想在那里提问。

于 2009-10-26T07:52:00.563 回答
2

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(注意分组是可配置的!)..

形式..

于 2014-01-08T18:55:26.647 回答
1

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

他们告诉你,你只需要一条线来激活它,但你会发现这是一个令人头疼的问题,而且比它值得做更多的工作强烈建议您坚持使用normal ListView,否则您会发现自己正在编写一个 1000 行的模型类...只需将 1 个字符串添加到ListView.

ObjectListView在您深入研究之前,请先了解有关此业务的真相...

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

于 2011-08-23T03:46:23.880 回答
0

尝试将虚拟模式下的普通 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 之外没有其他解决方案。

于 2014-04-26T21:06:31.103 回答