16

我试图了解如何最好地扩展ListBox控制。作为一种学习体验,我想构建一个ListBoxwhosListBoxItem显示 aCheckBox而不仅仅是文本。我使用 以基本方式工作ListBox.ItemTemplate,明确设置我想要数据绑定到的属性的名称。一个例子值一千字,所以...

我有一个用于数据绑定的自定义对象:

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实例上重用它,并为每个实例绑定IsChecked并绑定Content到任意属性名称?

4

3 回答 3

18

将 DataTemplate 创建为资源,然后使用 ListBox 的 ItemTemplate 属性引用它。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}"/>
于 2009-03-24T00:07:38.723 回答
17

最简单的方法可能是将DataTemplate作为资源放在应用程序中的某个TargetType位置,MyDataItem就像这样

<DataTemplate DataType="{x:Type MyDataItem}">
    <CheckBox IsChecked="{Binding Path=Checked}" Content="{Binding Path=DisplayName}" />
</DataTemplate>

您可能还必须xmlns在本地程序集中包含一个并通过它引用它。然后,每当您使用 a ListBox(或MyDataItem在 aContentPresenter或中使用 a 的任何其他东西ItemsPresenter)时,它都会使用它DataTemplate来显示它。

于 2009-03-24T13:46:21.503 回答
2

如果您想要一种方式显示,那么您可以使用转换器:

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 接口,该接口公开您希望数据模板绑定到的通用属性?

于 2009-03-24T06:05:50.860 回答