wpf 为 ItemsControl.ItemContainerStyle 指定 ControlTemplate

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3542381/
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-09-08 22:03:08  来源:igfitidea点击:

Specify ControlTemplate for ItemsControl.ItemContainerStyle

wpfitemscontrolcontroltemplateitemcontainerstyle

提问by Travis Heseman

The following is similar to what I'm trying to accomplish. However, I get the error

以下内容与我正在尝试完成的内容类似。但是,我收到错误

Invalid PropertyDescriptor value.

无效的 PropertyDescriptor 值。

on the Template Setter. I suspect it's because I didn't specify a TargetTypefor the Style; however, I don't know the container type for ItemsControl.

在模板上Setter。我怀疑这是因为我没有TargetTypeStyle;指定 a 但是,我不知道ItemsControl.

<ItemsControl>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <StackPanel>
                            <TextBlock Text="Some Content Here" />
                            <ContentPresenter />
                            <Button Content="Edit" />
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <!-- heterogenous controls -->
    <ItemsControl.Items> 
        <Button Content="Content 1" />
        <TextBox Text="Content 2" />
        <Label Content="Content 3" />
    </ItemsControl.Items>
</ItemsControl>

回答by Quartermeister

You can qualify the property name with the type name:

您可以使用类型名称限定属性名称:

<Setter Property="Control.Template">

The container for ItemsControlis normally a ContentPresenter, but if the child is a UIElementthen it won't use a container. In this case, all of the children are Controls, so the ItemContainerStylewill apply to them directly. If you added an item other than a UIElement, that setter would set the Control.Templateproperty on the ContentPresenter, which would succeed but have no effect.

for 的容器ItemsControl通常是 a ContentPresenter,但如果孩子是 aUIElement则它不会使用容器。在这种情况下,所有子项都是 Controls,因此ItemContainerStyle将直接应用于它们。如果您添加了 a 以外的项目UIElement,则该 setter 将在Control.Template上设置该属性ContentPresenter,这会成功但无效。

Actually, it sounds like what you want is to wrap each child in a container, even if they are already a UIElement. To do that, you will have to use a subclass of ItemsControl. You could use an existing one like ListBox, or you could subclass ItemsControland override GetContainerForItemOverrideand IsItemItsOwnContainerOverrideto wrap the items in your own container. You could wrap them in a ContentControland then use that as the TargetTypefor the Style.

实际上,听起来您想要的是将每个孩子包装在一个容器中,即使它们已经是UIElement. 为此,您必须使用ItemsControl. 您可以使用现有的,例如ListBox,或者您可以子类化ItemsControl和覆盖GetContainerForItemOverride并将IsItemItsOwnContainerOverride项目包装在您自己的容器中。你可以将它们包装在一个ContentControl,然后使用该作为TargetTypeStyle

public class CustomItemsControl
    : ItemsControl
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new ContentControl();
    }

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        // Even wrap other ContentControls
        return false;
    }
}

You will also need to set the TargetTypeon the ControlTemplateso that the ContentPresenterwill bind to the Contentproperty:

您还需要设置TargetTypeonControlTemplate以便ContentPresenter将绑定到Content属性:

<ControlTemplate TargetType="ContentControl">

回答by 000

Also if you only want to do all of it with XAML you can simply use ListBox instead of ItemsControl and define a style for ListBoxItem:

此外,如果您只想使用 XAML 完成所有操作,您可以简单地使用 ListBox 而不是 ItemsControl 并为 ListBoxItem 定义样式:

        <ListBox ItemsSource="{Binding Elements.ListViewModels}">
        <ListBox.Resources>
            <Style TargetType="ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <StackPanel>
                                <TextBlock>Some Content Here</TextBlock>
                                <ContentPresenter Content="{TemplateBinding Content}" />
                                <Button>Edit</Button>
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

Note that because I am using ListBox the container is ListBoxItem(Generally the container for WPF's default list control is always named the Item) so we create a style for ListBoxItem:

请注意,因为我使用的是 ListBox,所以容器是 ListBoxItem(通常 WPF 的默认列表控件的容器总是命名为 Item)所以我们为 ListBoxItem 创建一个样式:

<Style TargetType="ListBoxItem">

Then we create a new ControlTemplate for ListBoxItem. Please note that ContentPresenter is not used as it always appears in articles and tutorials, you need to template-bind it to Content property of ListBoxItem, so it will show the content for that item.

然后我们为 ListBoxItem 创建一个新的 ControlTemplate。请注意 ContentPresenter 没有使用,因为它总是出现在文章和教程中,您需要将它模板绑定到 ListBoxItem 的 Content 属性,以便它显示该项目的内容。

<ContentPresenter Content="{TemplateBinding Content}" />

I just had the same problem and fixed it this way. I dont wanted some functionalities of ListBox ( item selection ) and by using this technique the item selection does not work anymore.

我只是遇到了同样的问题并以这种方式修复了它。我不想要 ListBox(项目选择)的某些功能,通过使用这种技术,项目选择不再起作用。