DataTemplate中的样式是否仅应用于ItemsControl中的最后一项?

Sco*_*ott 11 wpf xaml styles datatemplate itemscontrol

在下面的XAML中,我有一个ItemsControl,它有三个DataObjects.
我使用DataTemplate将DataObjects显示为带有"X"的按钮.
Button使用样式设置其内容.

如果Setter.Value为"X",一切都很棒!
但是,如果我将Setter.Value更改为TextProperty为"X"的TextBlock,则X仅出现在最后一个Button(第三个DataObject)上,前两个Buttons为空.

这是一个错误,还是任何人都能解释为什么会这样?

注1)这是一个人为的例子来隔离遇到的问题.
注2)我已将两个Setter.Value选项放在代码中,这样您只需将其中一个注释掉即可重现成功和不成功的情况.
注3)看来,这个问题特定于'内容'属性的Setters.如果我使用Setter作为Background属性,它将正确应用于所有DataObjects.

<Grid>
    <Grid.Resources>
        <Style x:Key="myButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Content">
                <!--<Setter.Value>X</Setter.Value>-->
                <Setter.Value><TextBlock Text="X" /></Setter.Value>
            </Setter>
            <Setter Property="Background">
                <Setter.Value>
                    <SolidColorBrush Color="Red" />
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <ItemsControl>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type DataObject}">
                <Button Height="24" Width="24" Style="{StaticResource myButtonStyle}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.Items>
            <DataObject />
            <DataObject />
            <DataObject />
        </ItemsControl.Items>
    </ItemsControl>
</Grid>
Run Code Online (Sandbox Code Playgroud)

解:

不幸的是,当Content被设置为TextBlock而不是直接文本的控件时,我仍然无法解释为什么'Content'Setter无法处理除最后一个DataObject之外的所有DataObject.

但是,Dmitry建议使用"ContentTemplate"而不是"Content"是一种非常可接受的解决方法,仍然允许使用可重复使用的样式.

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="textBlockWithX">
            <TextBlock Text="X" />
        </DataTemplate>
        <Style x:Key="myButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="ContentTemplate" Value="{StaticResource textBlockWithX}" />
        </Style>
    </Grid.Resources>
    <ItemsControl>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type DataObject}">
                <Button Height="24" Width="24" Style="{StaticResource myButtonStyle}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.Items>
            <DataObject />
            <DataObject />
            <DataObject />
        </ItemsControl.Items>
    </ItemsControl>
</Grid>
Run Code Online (Sandbox Code Playgroud)

H.B*_*.B. 9

对此的答案实际上相当简单,每个视觉只能是一个对象的子节点,而不像文本那样"X"只是数据.

如果您创建这样的样式:

<Style>
    <Setter Property="Content">
        <Setter.Value>
             <TextBlock Text="X"/>
        </Setter.Value>
    </Setter>
<Style>
Run Code Online (Sandbox Code Playgroud)

只为应用了样式的所有实例创建了一个 TextBlock,因此TextBlock将在每个应用程序上"跳转"并最终到达最后一个项目.

如果您设置了,ContentTemplate则创建名称意味着一个模板,该模板用于为每个对象独立生成内容,因此您最终会为每个控件应用一个实例.


小智 6

这是一个工作样本:

<Window x:Class="Styles.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Styles"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <Style x:Key="A" TargetType="{x:Type Button}">
                <Style.Setters>
                    <Setter Property="Content" Value="X"></Setter>
                </Style.Setters>
            </Style>
        </Grid.Resources>
        <ItemsControl>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Height="24" Width="24" Style="{StaticResource A}">

                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.Items>
                <DataObject></DataObject>
                <DataObject></DataObject>
                <DataObject></DataObject>
            </ItemsControl.Items>
        </ItemsControl>
    </Grid>

</Window>
Run Code Online (Sandbox Code Playgroud)

Edit1 Doh ..有了它的工作,诀窍是使用ContentTemplate.

<Window x:Class="Styles.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Styles"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="A">
                <TextBlock>X</TextBlock>
            </DataTemplate>
        </Grid.Resources>
        <ItemsControl>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Height="24" Width="24" ContentTemplate="{StaticResource A}">

                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.Items>
                <DataObject></DataObject>
                <DataObject></DataObject>
                <DataObject></DataObject>
            </ItemsControl.Items>
        </ItemsControl>
    </Grid>

</Window>
Run Code Online (Sandbox Code Playgroud)

Edit2:更复杂的ContentTemplate示例:

<Window x:Class="Styles.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Styles"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="A">
                <StackPanel Width="30" Orientation="Horizontal">
                    <Grid Background="White" Width="10" Height="10"></Grid>
                    <Grid Background="Blue" Width="10" Height="10"></Grid>
                    <Grid Background="Red" Width="10" Height="10"></Grid>
                </StackPanel>
            </DataTemplate>
        </Grid.Resources>
        <ItemsControl>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Height="24" Width="34" ContentTemplate="{StaticResource A}">

                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.Items>
                <DataObject></DataObject>
                <DataObject></DataObject>
                <DataObject></DataObject>
            </ItemsControl.Items>
        </ItemsControl>
    </Grid>

</Window>
Run Code Online (Sandbox Code Playgroud)