AutoCompleteBox

129

В объекте AutoCompleteBox поле ввода совмещено с раскрывающимся списком подсказок. Такое средство встречается во многих местах, включая поле поиска Google на домашней странице и адресную строку браузера.

В Silverlight для этого реализован мощный элемент управления, предоставляющий несколько способов определения пунктов, появляющихся в раскрывающемся списке. Проще всего начать с обычного определения объекта AutoCompleteBox. При перетаскивании AutoCompleteBox из окна инструментов на страницу Visual Studio создает псевдоним input:

<UserControl x:Class="SilverlightTest.MainPage"
    xmlns:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input"
    ...
        <input:AutoCompleteBox x:Name="txtMonth"/>
</UserControl>

После добавления AutoCompleteBox в приложение создайте массив или список, содержащий коллекцию подсказок (без определенной последовательности), и присвойте коллекцию свойству AutoCompleteBox.ItemsSource. Обычно эта операция выполняется при первой загрузке страницы. Для этого добавьте коллекцию в конструктор страницы или обработчик события UserControl.Loaded:

public MainPage()
{
    InitializeComponent();
    txtMonth.ItemsSource = new List {"Январь", "Февраль", "Март",
            "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"};
}

Этого достаточно для реализации поведения, установленного по умолчанию. Когда пользователь вводит буквы в поле во время выполнения, появляется раскрывающийся список с подсказками. Чтобы выбрать предлагаемый элемент, не вводя все название месяца вручную, нужно щелкнуть на нем или прокрутить список с помощью клавиш со стрелками:

AutoCompleteBox в действии

Объект AutoCompleteBox предлагает варианты, но не диктует правила. Простого способа вынудить пользователя ограничиться предлагаемыми элементами списка не существует.

Можно задать другое поведение объекта AutoCompleteBox. Если присвоить свойству IsTextCompletionEnabled значение True, объект будет автоматически заполнять поле во время ввода. Например, если пользователь введет букву A, объект заполнит поле первым встретившимся подходящим вариантом Апрель. Предложенный фрагмент текста выделяется и подсвечивается. Это означает, что, если пользователь продолжит вводить буквы, они заменят предложенный фрагмент. При нажатии клавиши <Del> или <Backspace> предложенный фрагмент удаляется.

При чтении свойства AutoCompleteBox оно возвращает текст, отображаемый в поле в данный момент. Следовательно, если свойство IsTextCompletion равно True, возвращается автоматически вставленный текст подсказки.

Режим фильтрации

Обычно объект AutoCompleteBox фильтрует список связанных элементов, сравнивая начало каждого элемента с введенным текстом. Такое поведение можно изменить с помощью свойства FilterMode, которое принимает перечисление AutoCompleteFilterMode:

Элементы перечисления AutoCompleteFilterMode
Описание Имя
None Фильтрация не выполняется; в списке подсказок выводятся все элементы. Обычно этот режим используется при задании коллекции элементов с помощью запроса к базе данных или веб-службе
StartsWith Отображаются все элементы, начинающиеся с введенных букв, независимо от их регистра. Данный режим установлен по умолчанию
StartsWithCaseSensitive Отображаются все элементы, начинающиеся с введенных букв, с учетом их регистра
Contains Отображаются все элементы, в которых присутствует введенный фрагмент (не обязательно в начале), независимо от регистра букв
ContainsCaseSensitive Отображаются все элементы, в которых присутствует введенный фрагмент, с учетом регистра букв
Custom Пользовательская фильтрация; выполняется путем применения делегата, обрабатывающего свойство TextFilter или ItemFilter. При установке свойства TextFilter или ItemFilter свойство FilterMode автоматически получает значение Custom

Пользовательская фильтрация

Чтобы применить пользовательский фильтр, нужно установить свойство TextFilter или ItemFilter. Свойство TextFilter используется, если свойство ItemsSource содержит коллекцию строк, а свойство ItemFilter — если оно содержит коллекцию объектов другого типа.

В любом случае свойство TextFilter или ItemFilter принимает делегат, указывающий на метод, выполняющий пользовательскую фильтрацию. Метод получает два аргумента: текст, введенный пользователем на данный момент, и элемент списка подсказок, проверяемый на совпадение:

public bool ItemFilter(string text, object item)
{ ... }

Код метода выполняет сравнение и возвращает значение true, если элемент должен быть включен в раскрывающийся список подсказок, и false — если элемент должен быть пропущен.

Пользовательская фильтрация особенно полезна при сравнении текста со списком сложных объектов. В этом случае она позволяет использовать информацию, хранящуюся в разных свойствах. Предположим, информация о продукте хранится в объекте класса Product:

public class Product
{
        public string ProductName { get; set; }
        public string ProductCode { get; set; }

        public Product(string ProductName, string ProductCode)
        {
            this.ProductName = ProductName;
            this.ProductCode = ProductCode;
        }

        public override string ToString()
        {
            return ProductName;
        }
}

Необходимо создать объект AutoCompleteBox, проверяющий совпадение текста, введенного пользователем, с данными объекта Product. Сначала нужно заполнить коллекцию AutoCompleteBox.ItemsSource объектами Product:

txtProducts.ItemsSource = new List
{
                new Product("Апельсины Ставропольские", "Product-AP-12"),
                new Product("Ананасы Таджикистан", "Product-AN-08"),
                new Product("Яблоки Анис", "Product-APL-4")
};

Если не сделать больше ничего, объект AutoCompleteBox реализует стандартное поведение. Во время ввода букв объект AutoCompleteBox будет вызывать метод ToString() каждого объекта Product и применять введенный текст для фильтрации подсказок. Класс Product переопределяет метод ToString(), возвращая имя продукта, поэтому объект AutoCompleteBox найдет совпадения текста с именем продукта, что вполне приемлемо.

Однако пользовательская фильтрация может быть более совершенной. Например, можно задать сравнение вводимого текста как с ProductName, так и с ProductCode, включая в список объекты, для которых обнаружено любое совпадение:

public bool ProductItemFilter(string text, object item)
{
            Product product = (Product)item;

            // Совпадение засчитывается, если введенный 
            // текст есть в коде или в начале имени продукта
            return ((product.ProductName.StartsWith(text)) ||
                (product.ProductCode.Contains(text)));
}

Необходимо связать метод с объектом AutoCompleteBox при первой инициализации:

txtProducts.ItemFilter = ProductItemFilter;

Если пользователь введет текст APL, метод найдет код продукта Product-APL-4 и отобразит соответствующий элемент "Яблоки Анис" в списке подсказок:

Пользовательская фильтрация - объект обнаружен на основе фрагмента кода продукта
Пройди тесты
Лучший чат для C# программистов