如何使 ListBox.ItemTemplate 可重用/通用

发布于 2024-07-15 19:48:16 字数 1089 浏览 9 评论 0原文

我试图了解如何最好地扩展 ListBox 控件。 作为一次学习经历,我想构建一个 ListBox,其 ListBoxItem 显示一个 CheckBox 而不仅仅是文本。 我使用 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 实例上重用它,并为每个实例绑定 IsCheckedContent 到任意属性名称?

I am trying to understand how best to extend the ListBox control. As a learning experience, I wanted to build a ListBox whose ListBoxItems display a CheckBox instead of just text. I got that working in a basic fashion using the ListBox.ItemTemplate, explicitly setting the names of the properties I wanted to databind to. An example is worth a thousand words, so...

I've got a custom object for databinding:

public class MyDataItem {
    public bool Checked { get; set; }
    public string DisplayName { get; set; }

    public MyDataItem(bool isChecked, string displayName) {
        Checked = isChecked;
        DisplayName = displayName;
    }
}

(I build a list of those and set ListBox.ItemsSource to that list.) And my XAML looks like this:

<ListBox Name="listBox1">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding Path=Checked}" Content="{Binding Path=DisplayName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

This works. But I want to make this template reusable, i.e. I'll want to bind to other objects with properties other than "Checked" and "DisplayName". How can I modify my template such that I could make it a resource, reuse it on multiple ListBox instances, and for each instance, bind IsChecked and Content to arbitrary property names?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

染墨丶若流云 2024-07-22 19:48:16

创建 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}"/>

Create your DataTemplate as a resource and then reference it using the ItemTemplate property of the ListBox. MSDN has a good example

<Windows.Resources>
  <DataTemplate x:Key="yourTemplate">
    <CheckBox IsChecked="{Binding Path=Checked}" Content="{Binding Path=DisplayName}" />
  </DataTemplate>
...
</Windows.Resources>

...
<ListBox Name="listBox1"
         ItemTemplate="{StaticResource yourTemplate}"/>
瀞厅☆埖开 2024-07-22 19:48:16

最简单的方法可能是将 DataTemplate 作为 资源 放在应用程序中的某个位置,TargetTypeMyDataItem,例如您

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

可能还必须将 xmlns 包含到本地程序集中并通过它引用它。 然后,每当您使用 ListBox (或在 ContentPresenterItemsPresenter 中使用 MyDataItem 的任何其他内容)时,它都会使用此DataTemplate来显示它。

The easiest way is probably to put the DataTemplate as a resource somewhere in your application with a TargetType of MyDataItem like this

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

You'll probably also have to include an xmlns to your local assembly and reference it through that. Then whenever you use a ListBox (or anything else that uses a MyDataItem in a ContentPresenter or ItemsPresenter) it will use this DataTemplate to display it.

陈独秀 2024-07-22 19:48:16

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

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

If you wanted one way display then you could use a converter:

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();
    }
}

Then the xaml would look something like this:

<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>

That data template you could make generic like above. Two way binding would be a fair bit more difficult.

I think you are better off making your base classes implement a ICheckedItem interface which exposes the generic properties that you want the datatemplates to bind to?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文