Как сделать элемент ListBox.ItemTemplate многоразовые / общие
Я пытаюсь понять, как лучше продлить ListBox
управление. В качестве учебного опыта я хотел построить ListBox
чей ListBoxItem
s дисплей a CheckBox
вместо просто текста. Я получил, что работает в основном, используя ListBox.ItemTemplate
, явно устанавливая имена свойств, которые я хотел привязать к databind. Пример стоит тысячи слов...
у меня есть пользовательский объект для привязки данных:
public class MyDataItem {
public bool Checked { get; set; }
public string DisplayName { get; set; }
public MyDataItem(bool isChecked, string displayName) {
Checked = isChecked;
DisplayName = displayName;
}
}
(Я создаю список из них и устанавливаю ListBox.ItemsSource
в этот список.) И мой XAML выглядит так:
<ListBox Name="listBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=Checked}" Content="{Binding Path=DisplayName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
это работает. Но я хочу сделать этот шаблон многоразовым, т. е. я хочу привязаться к другим объектам со свойствами, отличными от "Checked" и "DisplayName". Как я могу изменить свой шаблон так, чтобы я мог сделать его ресурсом, повторно использовать его на нескольких ListBox
экземпляры, и для каждого экземпляра bind IsChecked
и Content
произвольные имена свойств?
3 ответов
самый простой способ, вероятно, чтобы поставить DataTemplate
как ресурс где-то в вашем приложении с TargetType
of MyDataItem
такой
<DataTemplate DataType="{x:Type MyDataItem}">
<CheckBox IsChecked="{Binding Path=Checked}" Content="{Binding Path=DisplayName}" />
</DataTemplate>
вероятно, Вам также придется включить xmlns
к вашей локальной сборке и ссылаться на нее через это. Тогда всякий раз, когда вы используете ListBox
(или что-нибудь еще, что использует MyDataItem
на ContentPresenter
или ItemsPresenter
) он будет использовать этот DataTemplate
, чтобы отобразить его.
создайте DataTemplate в качестве ресурса, а затем ссылаться на него, используя ItemTemplate свойство ListBox. MSDN имеет хороший пример
<Windows.Resources>
<DataTemplate x:Key="yourTemplate">
<CheckBox IsChecked="{Binding Path=Checked}" Content="{Binding Path=DisplayName}" />
</DataTemplate>
...
</Windows.Resources>
...
<ListBox Name="listBox1"
ItemTemplate="{StaticResource yourTemplate}"/>
Если вы хотите один способ отображения, то вы можете использовать конвертер:
class ListConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((IList<MyDataItem>)value).Select(i => new { Checked = i.Checked2, DisplayName = i.DisplayName2 });
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
тогда xaml будет выглядеть примерно так:
<Window.Resources>
<this:ListConverter x:Key="ListConverter" />
</Window.Resources>
<ListBox ItemsSource="{Binding Path=Items, Converter={StaticResource ListConverter}}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=Checked, Mode=OneWay}" Content="{Binding Path=DisplayName, Mode=OneWay}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
этот шаблон данных вы можете сделать общим, как указано выше. Двустороннее связывание было бы намного сложнее.
Я думаю, что вам лучше сделать ваши базовые классы реализуют интерфейс ICheckedItem, который предоставляет общие свойства, к которым вы хотите привязать datatemplates?