Lyandor Ответов: 2

Привязка свойств списка объектов


Я создаю пользовательский элемент управления WPF, который состоит из списка. Этот пользовательский элемент управления имеет свойство DependencyProperty, который привязан к ItemsSource элемента управления ListBox. Для примера предположим, что ListBox - это набор лиц со свойством Name, однако при необходимости его можно использовать и для других классов.

Что я уже пробовал:

список выглядит следующим образом:
<ListBox ItemsSource="{Binding Items, RelativeSource={RelativeSource TemplatedParent}">
     <ListBox.ItemTemplate>
         <DataTemplate>
             <TextBlock Text=""/>
         </DataTemplate>
     </ListBox.ItemTemplate>
</ListBox>


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

Свойства выглядят следующим образом:
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(IEnumerable), typeof(SearchListBox), new FrameworkPropertyMetadata(null) { BindsTwoWayByDefault = true });
public static readonly DependencyProperty ClassPropertyProperty = DependencyProperty.Register("ClassProperty", typeof(string), typeof(SearchListBox), new FrameworkPropertyMetadata(null));

public IEnumerable SearchResults
{
   get { return (IEnumerable)GetValue(SearchResultsProperty); }
   set {SetValue(SearchResultsProperty, value); }
}


Как я могу привязаться к собственности человека?

2 Ответов

Рейтинг:
1

Henrik Jonsson

Я думаю, что вы можете использовать DisplayMemberPath чтобы иметь возможность динамически выбирать именованное свойство через ClassProperty показывать:

<ListBox ItemsSource="{Binding Items, RelativeSource={RelativeSource TemplatedParent}}"  DisplayMemberPath="{Binding ClassProperty, RelativeSource={RelativeSource TemplatedParent}}">
     </ListBox>

Пожалуйста, обратите внимание, что ItemTemplate не может использоваться при использовании DisplayMemberPath.

Удачи.


Lyandor

Привет, Хенрик, спасибо, что уделили мне время. У меня есть несколько вопросов относительно вашего ответа:

Что делать,если я планирую привязаться к более чем 1 классу свойств? Допустим, класс Person имеет фамилию и имя? Насколько я знаю (что я не думаю, что это много), только 1 свойство может быть связано. Используя ItemTemplate, я могу сделать столько текстовых блоков, сколько мне нужно для отображения нужных свойств.

Поскольку элементы имеют тип IEnumerable, как я могу управлять кодом позади? Потому что я пробовал это сделать, и хотя я не пробовал запустить его, это не имеет для меня никакого смысла:

общественного строка ClassProperty
{
get {return(string)GetValue (Items.GetType (). GetProperty(propName));}
}

Рейтинг:
0

PureNsanity

Если вы собираетесь иметь различные шаблоны данных в списке в зависимости от типа, вы должны сделать что-то вроде этого:

<listbox itemssource="{Binding Items, RelativeSource={RelativeSource TemplatedParent}}">
    <listbox.resources>
        <datatemplate datatype="{x:Type viewModels:Person}">
            ...
        </datatemplate>
        <datatemplate datatype="{x:Type viewModels:OtherPossibleItemType}">
            ...
        </datatemplate>
    </listbox.resources>
</listbox>


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

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