Установите TextSearch.Text для WPF-ComboBoxItem через DataTemplate - PullRequest
5 голосов
/ 10 июля 2009

Я использую табличку с данными для визуализации некоторых элементов в ComboBox, ItemsSource связан с ObservableCollection. Для простоты, скажем, я поместил людей в ObservableCollection:

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Мой DataTemplate выглядит так:

<DataTemplate TargetType="{x:Type Person}">
  <StackPanel Orientation="Horizontal">
    <TextSearch.Text>
      <MultiBinding StringFormat="{} {0} {1}">
        <Binding Path="FirstName"/>
        <Binding Path="LastName"/>
      </MultiBinding>
    </TextSearch.Text>
    <TextBlock Text="{Binding FirstName}" Margin="2,0" />
    <TextBlock Text="{Binding LastName}"/>
  </StackPanel>
</DataTemplate>

Теперь я хочу включить автозаполнение для полных имен в ComboBox, не вводя третьего свойства в моем классе person. Следовательно, я не хочу использовать свойство TextSearch.TextPath для ComboBox, но вместо этого я хотел бы связать свойство TextSearch.Text-каждого ComboBoxItem в DataTemplate. К сожалению, когда я делаю это (который работает с MultiBinding и StringFormat, протестированными с Snoop), значение привязки регистрируется только для моей StackPanel, но с помощью Snoop (отличный инструмент) я обнаружил, что эта панель стека служит просто содержимым для некоторого дальнейшего ComboBoxItemTemplate , который ставит другую границу и т. д. и, наконец, ComboBoxItem-тег вокруг моей внешней StackPanel. Поэтому параметр TextSearch.Text неэффективен, поскольку он должен быть установлен в созданном ComboBoxItem, а не где-то внутри.

Вопрос сейчас: Как передать это свойство TextSearch.Text из моего DataTemplate на окружающий ComboBoxItem, используя только стили XAML и -Control-Templates? Решение может изменить шаблоны по умолчанию ControlTemplates ComboBox и ComboBoxItem и мой пользовательский (Item-) DataTemplate, но не использовать какой-либо Code-Behind или, по крайней мере, не слишком много. Возможно прикрепленное поведение тоже будет в порядке. Но я почти уверен, что должен быть способ заставить это работать без TemplateBinding или RelativeSource-вещи ... И, конечно, решение должно заставить мой выбор клавиатуры и завершение текста работать, s.th. если в списке содержатся Ганс Йозеф и Ганс Питер, то ввод «Ганса» должен автоматически выдвигать Ганса Йозефа, тогда как ввод «Ганса Р» достаточно быстро должен автоматически выполнять поиск Ганса Петера.

Какие-нибудь решения?

Ответы [ 2 ]

8 голосов
/ 17 ноября 2009

Краткий ответ: то, что вы хотите сделать, нельзя сделать напрямую в XAML, но есть и другие способы сделать это.

Длинный ответ: ComboBox ищет свойство TextSearch.Text непосредственно в элементах данных, хранящихся в коллекции Items или ItemsSource. Поэтому вы не можете установить свойство в шаблоне данных или стиле, потому что они применяются к объектам, используемым для отображения элементов данных, а не к самим элементам данных.

В частности, если вы посмотрите на примеры на странице класса класса *1005*, вы увидите, что они присоединяют свойство TextSearch.Text к объектам Image, которые входят в коллекцию ComboBox.Items. Вы можете сделать это в своей программе, сделав Person объектом DependencyObject, но я не думаю, что вы хотите установить свойство для каждого отдельного объекта таким образом.

У вас есть несколько вариантов здесь:

Если вы можете изменить класс Person, вы можете либо определить метод ToString (), чтобы он возвращал текст для автозаполнения, либо определить произвольное свойство, например, Fullname, и установить Textsearch.TextPath в ComboBox. Например:

public class Person
{
     string FirstName { get; set; }
     string LastName {get; set; }
     string FullName { get { return String.Format("{0} {1}", FirstName, LastName); } }
}

и

<ComboBox TextSearch.TextPath="FullName" ItemsSource="collectionOfPersons"/>

В качестве альтернативы, если вы не хотите прикасаться к Person, вы можете создать класс-оболочку, который предоставляет эти свойства.

1 голос
/ 12 ноября 2009

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

<ComboBox.ItemContainerStyle>
    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="TextSearch.Text">
            <Setter.Value>
                <MultiBinding StringFormat="{} {0} {1}">
                    <Binding Path="FirstName"/>
                    <Binding Path="LastName"/>
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>
</ComboBox.ItemContainerStyle>
...