Нам нужно заполнить выпадающее поле с данными, полученными из базы данных. Поскольку число потенциальных извлеченных записей может быть в тысячах, мы ограничиваем список, даже не вызывая базу данных, пока пользователь не ввел первые 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;
}
}
}
Вы написали, что вам нужно. Но что происходит с вашим кодом в настоящее время? –
Извините, когда установлен параметр ItemsSource combobox, первый соответствующий элемент подсвечивается, и список удаляется. По мере продолжения ввода список становится меньше и меньше, пока не останется только один элемент. Это то, что нужно. Но если вы нажмете клавишу backspace, она не вернется к предыдущему фильтру, который будет показывать дополнительные элементы (например, после того, как вы покажете 000-Test111, вы не сможете вернуться к 000-Test11). – j2associates
Вызывает ли comboBox1Editor_TextChanged даже вызов с помощью клавиши backspace? – Paparazzi