Подтвердить что ты не робот

С# listbox Синтаксис коллекции

Во время обучения С# довольно быстро, я наткнулся на эту проблему синтаксиса коллекции.

Я добавил несколько объектов своего типа MyItem в listbox lstData. Теперь мне нужно искать в этом списке и думать об использовании элегантной нотации LINQ, например:

lstData.Items.Where(x => x.Text == SearchString)

но элементы списка не имеют .Where(), хотя я включил "using System.Linq;" Пространство имен.

Итак, я попробовал:

foreach (MyItem item in (MyItem)lstData.Items)

но это дает ошибку сборки: невозможно преобразовать тип 'System.Windows.Forms.ListBox.ObjectCollection' в 'MySandbox.frmListboxDemo.MyItem'.

Мне удалось написать что-то работоспособное:

        for (int i = 0; i < lstData.Items.Count; i++)
        {
            MyItem item = (MyItem)lstData.Items[i];
            if (item.Text == SearchString)
            {
                lstData.SetSelected(i, true);
                break;
            }
        }

и аналогичную версию, например:

        var item_enum = lstData.Items.GetEnumerator();
        while (item_enum.MoveNext()) { etc etc... }

который оказался длиннее на 2 строки и не смог определить, что может заменить "var".

Я не уверен, что понимаю, как использовать Collections, ObjectCollections, Enumerators и т.д., но я очень хочу учиться. Особенно если версия .Where() возможна и/или лучше.


Спасибо за все ваши ответы. Я закончил с этим решением:

        var item_iter = lstData.Items.Cast<MyItem>()
                          .Where(x => x.Text.Trim().ToLower() == txtItemName.Text);
        foreach (MyItem item in item_iter)
        {
            int i = lstData.Items.IndexOf(item);
            lstData.SetSelected(i, true);
            break;
        }

Я не знаю, действительно ли это намного лучше, чем "fortran" (см. выше), но он учит меня методам, которые я могу использовать в других запросах С#.

4b9b3361

Ответ 1

Сначала попробуйте использовать Cast<T>, чтобы выполнить приведение к типу, который вы ожидаете. То есть:

lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)

Ответ 2

Коллекция элементов не является строго типизированной коллекцией. Вы можете использовать методы расширения IEnumerable<T>.OfType() или IEnumerable<T>.Cast(), чтобы получить запись в мир LINQ, где вы можете отфильтровать свои записи:

var filteredItems = lstData.Items.OfType<MyItem>().Where(i => i.Prop == val);

Разница между Cast и OfType заключается в следующем:

  • OfType<T> будет просто возвращать элементы, которые можно использовать для типа T
  • Cast<T> завершится с ошибкой, когда по крайней мере один элемент находится в коллекции, которая не может быть записана в T

Ответ 3

ListBox.ObjectCollection реализует IEnumerable, но не общий IEnumerable<T>, который требуется большинству методов Linq.

Один из способов добраться до IEnumerable<T> И решить проблему кастинга за один шаг - использовать Cast<T>:

lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)

Ответ 4

Попробуйте сделать список из элементов:

(new ListBox()).Items.OfType<ListViewItem>().Where(......); 

Вероятно, причина в том, что она была изначально построена с более ранней версией .net