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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/675671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 12:58:51  来源:igfitidea点击:

How to make a ListBox.ItemTemplate reusable/generic

c#wpfdata-bindingitemtemplate

提问by Matt Winckler

I am trying to understand how best to extend the ListBoxcontrol. As a learning experience, I wanted to build a ListBoxwhose ListBoxItems display a CheckBoxinstead 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...

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

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.ItemsSourceto that list.) And my XAML looks like this:

(我构建了一个列表并设置ListBox.ItemsSource为该列表。)我的 XAML 如下所示:

<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 ListBoxinstances, and for each instance, bind IsCheckedand Contentto arbitrary property names?

这有效。但我想让这个模板可重用,即我想绑定到具有“Checked”和“DisplayName”以外的属性的其他对象。如何修改我的模板,这样我可以让它变成一个资源,再用它在多个ListBox实例,每个实例,绑定IsCheckedContent任意属性名称?

采纳答案by Bryan Anderson

The easiest way is probably to put the DataTemplateas a resourcesomewhere in your application with a TargetTypeof MyDataItemlike this

最简单的方法可能是将资源DataTemplate作为资源放在您的应用程序中的某个地方TargetTypeMyDataItem就像这样

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

You'll probably also have to include an xmlnsto your local assembly and reference it through that. Then whenever you use a ListBox(or anything else that uses a MyDataItemin a ContentPresenteror ItemsPresenter) it will use this DataTemplateto display it.

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

回答by MrTelly

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

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

回答by Jake Ginnivan

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:

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

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?

我认为您最好让您的基类实现一个 ICheckedItem 接口,该接口公开您希望数据模板绑定到的通用属性?