Ответ 1
Сначала попробуйте использовать Cast<T>
, чтобы выполнить приведение к типу, который вы ожидаете. То есть:
lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)
Во время обучения С# довольно быстро, я наткнулся на эту проблему синтаксиса коллекции.
Я добавил несколько объектов своего типа 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" (см. выше), но он учит меня методам, которые я могу использовать в других запросах С#.
Сначала попробуйте использовать Cast<T>
, чтобы выполнить приведение к типу, который вы ожидаете. То есть:
lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)
Коллекция элементов не является строго типизированной коллекцией. Вы можете использовать методы расширения IEnumerable<T>.OfType()
или IEnumerable<T>.Cast()
, чтобы получить запись в мир LINQ, где вы можете отфильтровать свои записи:
var filteredItems = lstData.Items.OfType<MyItem>().Where(i => i.Prop == val);
Разница между Cast и OfType заключается в следующем:
OfType<T>
будет просто возвращать элементы, которые можно использовать для типа TCast<T>
завершится с ошибкой, когда по крайней мере один элемент находится в коллекции, которая не может быть записана в T ListBox.ObjectCollection
реализует IEnumerable
, но не общий IEnumerable<T>
, который требуется большинству методов Linq.
Один из способов добраться до IEnumerable<T>
И решить проблему кастинга за один шаг - использовать Cast<T>
:
lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)
Попробуйте сделать список из элементов:
(new ListBox()).Items.OfType<ListViewItem>().Where(......);
Вероятно, причина в том, что она была изначально построена с более ранней версией .net