Стиль в DataTemplate применяется только к последнему элементу в ItemsControl?

В XAML ниже, у меня есть ItemControl, который имеет три DataObjects.
Я использую DataTemplate для отображения DataObjects как кнопок с "X" на них.
Кнопка использует стиль для установки своего содержимого.

Если Setter.Value является "X" , все отлично работает!
Однако, если я изменил Setter.Value на TextBlock, TextProperty которого "X" , , X появляется только на последней кнопке (третий объект DataObject), а первые две кнопки пустые.

Является ли это ошибкой или кто-нибудь может объяснить, почему это происходит?

Примечание 1) Это надуманный пример для изоляции проблемы. Примечание 2) Я поместил обе опции Setter.Value в код, чтобы вы могли воспроизвести как успешные, так и неудачные случаи, просто попросив одного из них прокомментировать. Примечание 3) Кажется, эта проблема специфична для Setters для свойства Content. Если я использую свойство Setter for Background, оно верно относится ко всем объектам DataObject.

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

Решение:

К сожалению, я до сих пор не могу объяснить, почему "Content" Setter не работает на всех, кроме последнего объекта DataObject, когда Content установлен как элемент управления, например TextBlock, а не прямой текст.

Однако предложение Дмитрия об использовании настройки ContentTemplate вместо "Контента" является очень приемлемым обходным решением, которое по-прежнему позволяет использовать повторно используемый стиль.

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

Ответ 1

Здесь рабочий пример:

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

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>

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>

Ответ 2

Ответ на это довольно простой на самом деле, каждый визуал может быть только потомком одного объекта, в отличие от текста типа "X", который является просто данными.

Если вы создаете такой стиль:

<Style>
    <Setter Property="Content">
        <Setter.Value>
             <TextBlock Text="X"/>
        </Setter.Value>
    </Setter>
<Style>

Создается только один TextBlock для всех экземпляров, на которые применяется стиль, поэтому TextBlock будет "прыгать" в каждом приложении и заканчиваться последним элементом.

Если вы установите ContentTemplate, но создаете, так как имя подразумевает шаблон, который используется для независимого создания контента для каждого объекта, поэтому вы получаете один экземпляр на элемент управления, в котором применяется стиль.