2013-08-02 4 views
1

У меня есть следующая проблема. У меня есть WPF Listbox, который связан с ObservableCollection. Теперь я хочу отфильтровать элементы в поле с полной текстовой строкой.C# Фильтр списка с Linq полнотекстовый поиск

Я делаю это, запустив запрос linq на ObservableCollection и привязывая список к результату запроса. Он работает вообще, но есть некоторые поведения, которые я не могу объяснить.

Пример записи из списка: CMSRC_XXX_ADDR, CMDST_XXX_ADDR, TXDAT_DMA_ST_ADDR ...

Поисковые запросы, которые работают: АДРЕСА, XXX, XX, ADD, CM

Запросы поиска, которые НЕ работают: CMS, CMSR, ...

Когда я печатаю CM, он все еще показывает запись CMSRC_XXX_ADDR. Когда я вхожу CMS, CMSRC_XXX_ADDR больше не показан.

Кто-нибудь знает почему? Надеюсь, мой вопрос ясен. Спасибо за помощь.

С уважением Dominik

 string txtOrig = text; 
     string lower = txtOrig.ToLower(); 
     string normalize = txtOrig.Normalize(); 

     var bitfieldsfiltered = from bit in bitfields 
           let name = bit.name_ 
           where 
           name.ToLower().StartsWith(lower) 
           || name.StartsWith(txtOrig) 
           || name.Normalize().StartsWith(normalize) 
           || name.ToLower().Contains(lower) 
           || name.Contains(txtOrig) 
           || name.Normalize().Contains(normalize) 
           || name.ToLower().EndsWith(lower) 
           || name.EndsWith(txtOrig) 
           || name.Normalize().EndsWith(normalize) 
           || name.ToLower().Equals(lower) 
           || name.Equals(txtOrig) 
           || name.Normalize().Equals(normalize) 
           select bit; 
     list_box.ItemsSource = bitfields; 

UPDATE: ошибки не существует. Данные в ярлыках не были данными в списке. Недостаток подчеркивания был вызван признакомAccessKey.

+0

Wow! Почему вы не используете одно из перечислений StringComparison? Он может упростить вашу логику примерно на 66% и облегчить ее отладку. Просто любопытно? –

+0

@GarryVass, потому что он может не знать о таком перечислении. –

+0

@ user2591237, если вы перепробируете свой вопрос, чтобы включить, что вы счастливы принять улучшения логики/эффективности? –

ответ

0

Есть несколько вещей, которые можно сделать, чтобы исправить это поведение. Для начала перейдите к своему решению и «Добавить» -> «Новый проект» -> «Тест» -> «Проект тестирования модулей». Это Vs2012, а в Vs2010 меню будут немного отличаться.

После инициализации тестового проекта сделайте «Добавить» -> «Новый элемент» -> «Класс». Затем вставьте следующий код в этот класс ...

[TestClass] 
public class MyQueryUnitTests 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query("ADDR"); 
     Assert.IsTrue(result.Count==3); 
    } 
    [TestMethod] 
    public void TestMethod2() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query("XXX"); 
     Assert.IsTrue(result.Count == 2); 
    } 
    [TestMethod] 
    public void TestMethod3() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query("CMS"); 
     Assert.IsTrue(result.Count==1); 
    } 
    [TestMethod] 
    public void TestMethod4() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query("CMSR"); 
     Assert.IsTrue(result.Count == 1); 
    } 
    [TestMethod] 
    public void TestMethod5() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query("CM"); 
     Assert.IsTrue(result.Count == 2); 
    } 
    [TestMethod] 
    public void TestMethod6() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query("DUMMY"); 
     Assert.IsTrue(result.Count == 2); 
    } 
    [TestMethod] 
    public void TestMethod7() 
    { 
     BitQuery bitQuery = new BitQuery(); 
     var result = bitQuery.Query(""); 
     Assert.IsTrue(result.Count == 5); 
    } 
} 
public class BitQuery 
{ 
    public ObservableCollection<bit> bitfields = new ObservableCollection<bit>(); 
    public BitQuery() 
    { 
     bitfields.Add(new bit { name_ = "CMSRC_XXX_ADDR" }); 
     bitfields.Add(new bit { name_ = "CMDST_XXX_ADDR" }); 
     bitfields.Add(new bit { name_ = "TXDAT_DMA_ST_ADDR" }); 
     bitfields.Add(new bit { name_ = "WWWW_DUMMY" }); 
     bitfields.Add(new bit { name_ = "ABCDE_DUMMY" }); 
    } 
    public List<bit> Query (string text) 
    { 
     string txtOrig = text; 
     string lower = txtOrig.ToLower(); 
     string normalize = txtOrig.Normalize(); 
     var bitfieldsfiltered = from bit in bitfields 
           let name = bit.name_ 
           where IsMatch(txtOrig, name) 
           select bit; 
     return bitfieldsfiltered.ToList(); 
    } 
    private bool IsMatch(string txtOrig, string name) 
    { 
     if (name.StartsWith(txtOrig, StringComparison.InvariantCultureIgnoreCase)) return true; 
     if (name.IndexOf(txtOrig, 0, StringComparison.OrdinalIgnoreCase) >= 0) return true; 
     return false; 
    } 
} 
public class bit 
{ 
    public string name_ { get; set; } 
    public override string ToString() 
    { 
     return name_; 
    } 
} 

И затем сообщите Visual Studio, чтобы запустить модульные тесты. VS откроет окно, которое подсвечивается различными цветами и запускает тесты.

Все тесты показывают, что проблема, о которой вы описали, исправлена, и вы возвращаете ожидаемые результаты!

непосредственный интерес является замена ваших длительных «или» статей с простым методом ...

private bool IsMatch(string txtOrig, string name) 
    { 
     if (name.StartsWith(txtOrig, StringComparison.InvariantCultureIgnoreCase)) return true; 
     if (name.IndexOf(txtOrig, 0, StringComparison.OrdinalIgnoreCase) >= 0) return true; 
     return false; 
    } 

--- который делает по существу то же самое. ПРИМЕЧАНИЕ. Вам нужно будет добавить еще несколько модульных тестов, чтобы охватить все различные условия. Если у вас очень высокий уровень уверенности в том, что ваш запрос является надежным и неизменно точным, вы можете подключить его обратно к своему списку.

Другое изменение стоит брать на борт эта линия ...

return bitfieldsfiltered.ToList(); 

Это принимает результат LINQ и «запирает его вниз». В исходном коде вы оставили его как неоплаченный запрос (который может или не может повлиять на этот конкретный случай, но всегда полезно заблокировать его, если вы представляете что-то на поверхности пользователя).

Итак, ваши запросы «CMS» и «CMSR» работают сейчас, и у вас есть некоторые модульные тесты, где вы можете ввести дополнительные условия и быть уверенными в том, что все это работает.

+0

Спасибо большое! Я хотел бы проголосовать, но у меня пока нет 15 репутаций. – user2591237

+0

Вам не нужно rep, чтобы поместить «Принять» на ответ (т. Е. Галочку под дисплеем голосования).Это будет означать, что вы довольны ответом, а также будете держать меня в курсе любых будущих вопросов, которые вы публикуете. –

0

Ваш код очень неэффективен, и вы проверяете одно и то же несколько раз. Вы можете просто позвонить

name.ToLower().Contains(lower) 

вместо

name.ToLower().Contains(lower) 

и

name.ToLower().StartsWith(lower) 

и

name.ToLower().Equals(lower) 

и

name.ToLower().EndsWith(lower) 

Попробуйте заменить всю where статью с этим:

where name.ToLower().Contains(lower) || name.Normalize().Contains(normalize) 

или, может быть, даже это:

where name.ToLower().Contains(lower) 

Вы должны получить лучшие результаты тогда.

UPDATE >>>

Когда мне нужно фильтровать коллекцию, я использую дополнительный сбор, чтобы моя оригинальная коллекция остается неизменной.Похоже, вы отфильтровываетесь в коллекции bitfieldsfiltered, но затем с помощью вашей коллекции bitfields в качестве значения ListBox.ItemsSource ... разве вы не должны отображать коллекцию bitfieldsfiltered?

+0

Откуда возникает ошибка, которую он описывает? Или это исправить ошибку? –

+0

@Sheridan Большое спасибо за вашу помощь. Именно так я и сделал это в первую очередь. Но это не исправляет ошибку, и такая же ошибка возникает снова. Вот почему добавлено много условий OR. – user2591237

+0

@sheridan Вы правы! Это была только ошибка в моем примере кода. Не в моем реальном коде. Но спасибо большое! Я нашел ошибку. В списке были другие данные, чем показано, потому что подчеркивание не было показано ярлыком wpf. – user2591237

Смежные вопросы