为 ItemsControl.ItemContainerStyle 指定 ControlTemplate

发布于 2024-09-15 15:59:50 字数 1178 浏览 8 评论 0原文

以下内容与我想要完成的任务类似。但是,我收到错误

PropertyDescriptor 值无效。

在模板 Setter 上。我怀疑这是因为我没有为Style指定TargetType;但是,我不知道 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>

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

Invalid PropertyDescriptor value.

on the Template Setter. I suspect it's because I didn't specify a TargetType for the Style; however, I don't know the container type for 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>

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

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

发布评论

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

评论(2

泅人 2024-09-22 15:59:50

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

<Setter Property="Control.Template">

ItemsControl 的容器通常是 ContentPresenter,但如果子项是 UIElement,则它不会使用容器。在本例中,所有子级都是 Control,因此 ItemContainerStyle 将直接应用于它们。如果您添加了 UIElement 以外的项目,该设置器将在 ContentPresenter 上设置 Control.Template 属性,该属性会成功,但不会影响。

实际上,听起来您想要的是将每个子元素包装在一个容器中,即使它们已经是一个 UIElement 。为此,您必须使用 ItemsControl 的子类。您可以使用现有的,例如 ListBox,也可以子类 ItemsControl 并覆盖 GetContainerForItemOverrideIsItemItsOwnContainerOverride 将项目包装在您自己的容器中。您可以将它们包装在 ContentControl 中,然后将其用作 StyleTargetType

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

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

您还需要在 ControlTemplate 上设置 TargetType,以便 ContentPresenter 绑定到 Content 属性:

<ControlTemplate TargetType="ContentControl">

You can qualify the property name with the type name:

<Setter Property="Control.Template">

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

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 ItemsControl and override GetContainerForItemOverride and IsItemItsOwnContainerOverride to wrap the items in your own container. You could wrap them in a ContentControl and then use that as the TargetType for the Style.

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 TargetType on the ControlTemplate so that the ContentPresenter will bind to the Content property:

<ControlTemplate TargetType="ContentControl">
魄砕の薆 2024-09-22 15:59:50

另外,如果您只想使用 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>

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

<Style TargetType="ListBoxItem">

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

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

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

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:

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

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

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

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