2012-05-18 6 views
2

Нам нужно заполнить выпадающее поле с данными, полученными из базы данных. Поскольку число потенциальных извлеченных записей может быть в тысячах, мы ограничиваем список, даже не вызывая базу данных, пока пользователь не ввел первые 5 символов в поле со списком. Затем список заполняется и постепенно фильтруется как пользовательские ключи в дополнительных символах с помощью combobox.Items.Filter.ComboBox с прогрессивным автозаполнением

Проблема в том, что процесс не является обратимым. Предположим, что пользователь вошел в 000-Test11, и то, что отображается, 000-Test11 и 000-Test111. Если пользователь набирает обратное пространство, то поле со списком должно вернуться к 000-Test1 и показать выше в дополнение к 000-Test12, 000-Test13 и т. Д.

Логика в текстовом редакторе текстового редактора изменена. поток MSDN - Implimenting AutoComplete combobox - Yiling Lai, Rovi Corporation ответ: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/cec1b222-2849-4a54-bcf2-03041efcf304/.

Вот код, демонстрирующий проблему, которую мы имеем.

класс StudyProxy:

namespace WPFTesting 
    { 
     public class StudyProxy 
     { 
      public int StudyID { get; set; } 
      public string StudyNumber { get; set; } 
      public string Title { get; set; } 

      public StudyProxy Init() 
      { 
       this.Title = this.StudyNumber; 
       return this; 
      } 
     } 
    } 

Часть XAML:

<Window x:Class="WPFTesting.SelectStudyScreen" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       Height="300" Width="300" SizeToContent="WidthAndHeight"> 
     <Grid> 
      <DockPanel Height="250" Width="250"> 
       <ComboBox DockPanel.Dock="Top" VerticalAlignment="Top" Name="comboBox1" 
         IsEditable="True" IsReadOnly="False" Margin="10" 
         DisplayMemberPath="StudyNumber" SelectedValuePath="StudyID" 
         SelectionChanged="comboBox1_SelectionChanged"/> 
       <DataGrid Name="dataGrid1" /> 
      </DockPanel> 
     </Grid> 
    </Window> 

Код позади:

using System; 
    using System.Windows; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.Diagnostics; 
    using System.Windows.Controls; 
    using System.Windows.Input; 
    using System.Windows.Controls.Primitives; 
    using System.Runtime.Serialization; 

    namespace WPFTesting 
    { 
     /// <summary> 
     /// Interaction logic for SelectStudyScreen.xaml 
     /// </summary> 
     public partial class SelectStudyScreen 
     { 
      private Popup _comboBox1Popup; 
      private TextBox _comboBox1Editor; 
      private StudyProxy _currentItem; 

      public SelectStudyScreen() 
      { 
       InitializeComponent(); 

       comboBox1.Loaded += new RoutedEventHandler(comboBox1_Loaded); 
      } 

      private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e) 
      { 
       if (comboBox1.SelectedIndex == -1) 
       { 
        dataGrid1.ItemsSource = null; 
       } 
       else 
       { 
        _currentItem = comboBox1.SelectedItem as StudyProxy; 
        List<string> studyIDs = new List<string>(new string[] { comboBox1.SelectedValue.ToString() }); 
       } 
      } 

      private void comboBox1_Loaded(object sender, RoutedEventArgs e) 
      { 
       _comboBox1Popup = comboBox1.Template.FindName("PART_Popup", comboBox1) as Popup; 
       _comboBox1Editor = comboBox1.Template.FindName("PART_EditableTextBox", comboBox1) as TextBox; 

       if (_comboBox1Editor != null) 
       { 
        _comboBox1Editor.KeyDown += new System.Windows.Input.KeyEventHandler(comboBox1Editor_KeyDown); 
        _comboBox1Editor.TextChanged += new TextChangedEventHandler(comboBox1Editor_TextChanged); 
        _comboBox1Editor.PreviewKeyDown += new KeyEventHandler(comboBox1Editor_PreviewKeyDown); 
       } 
      } 

      void comboBox1Editor_PreviewKeyDown(object sender, KeyEventArgs e) 
      { 
       if (_comboBox1Editor.Text != comboBox1.Text) 
       { 
       } 
      } 

      void comboBox1Editor_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) 
      { 
      } 

      private void comboBox1Editor_TextChanged(object sender, TextChangedEventArgs e) 
      { 
       string text = (sender as TextBox).Text.Trim(); 
       if (text.Length < 5) 
       { 
        _comboBox1Popup.IsOpen = false; 
       } 
       else if (text.Length == 5) 
       { 
        _comboBox1Popup.IsOpen = false; 

        comboBox1.ItemsSource = GetTestData(); 
       } 
       else 
       { 
        // Adapted 
        // From: Implimenting AutoComplete combobox - Yiling Lai, Rovi Corporation answer 
        // Link: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/cec1b222-2849-4a54-bcf2-03041efcf304/ 
        comboBox1.Items.Filter += a => 
        { 
         if ((a as StudyProxy).StudyNumber.StartsWith(text, StringComparison.OrdinalIgnoreCase)) 
         { 
          return true; 
         } 
         return false; 
        }; 
        _comboBox1Popup.IsOpen = true; 
       } 
      } 

      private List<StudyProxy> GetTestData() 
      { 
       List<StudyProxy> list = new List<StudyProxy>(); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test1" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test11" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test111" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test1111" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test12" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test122" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test1222" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test13" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test133" }.Init()); 
       list.Add(new StudyProxy() { StudyID = 1, StudyNumber = "000-Test1333" }.Init()); 

       return list; 
      } 
     } 
    } 
+0

Вы написали, что вам нужно. Но что происходит с вашим кодом в настоящее время? –

+0

Извините, когда установлен параметр ItemsSource combobox, первый соответствующий элемент подсвечивается, и список удаляется. По мере продолжения ввода список становится меньше и меньше, пока не останется только один элемент. Это то, что нужно. Но если вы нажмете клавишу backspace, она не вернется к предыдущему фильтру, который будет показывать дополнительные элементы (например, после того, как вы покажете 000-Test111, вы не сможете вернуться к 000-Test11). – j2associates

+0

Вызывает ли comboBox1Editor_TextChanged даже вызов с помощью клавиши backspace? – Paparazzi

ответ

0

Это может получить вас там. Я связал текст, и он получил вызов в обратном пространстве.

Text="{Binding Path=CBvalue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 

Я делаю что-то подобное, но я продолжаю и загружаю более 20 000 значений. Я использую текстовое поле и отдельный список. С виртуализацией это не большая сделка со всеми 20 000. Затем по изменению текста я жду 1 секунду, используя DispatcherTimer, прежде чем фильтровать, чтобы он не фильтровал во время набора текста. Затем DispatchTimer вызывает BackGroundWorker, чтобы применить фильтр, чтобы я мог отменить BackGroundWorker. Я просто привязываю ListView к списку, который фильтруется с помощью LINQ. Круглые поездки в DB медленны. Мой список полустатический.

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