21

以下类似于我要完成的工作。但是,我得到了错误

无效的 PropertyDescriptor 值。

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

2 回答 2

43

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

<Setter Property="Control.Template">

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

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

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

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

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

<ControlTemplate TargetType="ContentControl">
于 2010-08-22T17:04:36.803 回答
3

此外,如果您只想使用 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 的某些功能(项目选择),并且通过使用这种技术,项目选择不再起作用。

于 2011-09-19T03:32:45.993 回答