为什么我的风格不适用?

时间:2016-11-02 17:15:11

标签: wpf xaml listview styles

我的问题与this post中的问题相同。但是,由于这篇旧帖子四年没有答案,我想也许有新的见解为什么这不应该像它应该的那样工作。

在我的窗口资源中,我为TextBlock定义了一个简单的样式。该样式没有x:Key属性,因此它应该应用于我窗口中的所有TextBlock控件,这些控件没有自己的样式。

然后我创建一个ListView,其中GridView被定义为其视图。 ListView定义了四个列,使用包含CellTemplate的显式TextBlock定义了两列,并且在没有明确CellTemplate的情况下定义了两列。

这是我完整的XAML代码(代码下面的问题):

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    mc:Ignorable="d"
    Title="MainWindow" SizeToContent="WidthAndHeight">

<Window.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="TextTrimming" Value="CharacterEllipsis" />
        <Setter Property="Background" Value="Aqua" />
    </Style>

    <Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    </Style>
</Window.Resources>

<ListView ItemContainerStyle="{StaticResource ListViewItemStyle}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Bottom" Width="50" DisplayMemberBinding="{Binding Bottom}" />
            <GridViewColumn Header="Left" Width="50">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Left}" TextAlignment="Center" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="Right" Width="50">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Right}" TextAlignment="Right" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="Top" Width="50" DisplayMemberBinding="{Binding Top}" />
        </GridView>
    </ListView.View>
    <ListView.Items>
        <Thickness>1,2,3,4</Thickness>
        <Thickness>5,6,7,8</Thickness>
        <Thickness>9,10</Thickness>
    </ListView.Items>
</ListView>
</Window>

如果我运行此代码,我可以看到,应该应用于所有TextBlock控件的TextBlock样式仅在不具备的列中有效一个明确的CellTemplate

为什么?

当我检查可视树时,我可以看到,工作列(那些没有 a CellTemplate)是由TextBlock构成的,我的风格应用于它,虽然不起作用的列( 一个CellTemplate)是由内部ContentPresenter的{​​{1}}组成的,但是TextBlock完全没有风格。

1 个答案:

答案 0 :(得分:2)

这种行为实际上是设计的。 This link描述了正在发生的事情。 2006年10月还有一个关于Microsoft Connect的错误报告。不幸的是,给定链接中错误报告的原始链接不再起作用。

我将在以后回复来自Connect的错误报告的答案,以防将来链接发生故障。

  

这种行为是“按设计”。这就是原因。模板被视为封装边界。由这些模板生成的元素属于此边界。查找具有匹配TargetType的样式将在此边界处停止。因此,通过模板生成的repro中的TextBlock不会拾取相关的Style。而在模板外定义的TextBlock确实如此。   解决此问题的一种方法是为Style指定一个显式名称,并在模板中的TextBlock上通过此名称引用样式。

您看到他们已经为您的问题提供了解决方法。他们声明您应该在TextBlock名称中提供Window.Resources样式,并在模板中引用该样式。

我认为这不是你真正想要的,因为在这种情况下,样式不会自动应用于所有TextBlocks(在DataTemplate之外)。因此,在引用样式时,您可以在Windows.Resources属性中执行一些小技巧,而不是使BasedOn中的样式具有显式名称。您可以指定类似的类型,而不是指定样式的名称。

<GridViewColumn Header="Left" Width="50">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <DataTemplate.Resources>
                <Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
            </DataTemplate.Resources>
            <TextBlock Text="{Binding Left}" TextAlignment="Center" />
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

使用这种方法,您仍然可以不为样式指定名称,并且样式将应用于所有TextBlock。

作为参考,整个Window XAML看起来像这样。现在,GridView中的所有列都具有相同的样式。

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    mc:Ignorable="d"
    Title="MainWindow" SizeToContent="WidthAndHeight">

    <Window.Resources>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="TextTrimming" Value="CharacterEllipsis" />
            <Setter Property="Background" Value="Aqua" />
        </Style>

        <Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </Window.Resources>

    <ListView ItemContainerStyle="{StaticResource ListViewItemStyle}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Bottom" Width="50" DisplayMemberBinding="{Binding Bottom}" />
                <GridViewColumn Header="Left" Width="50">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <DataTemplate.Resources>
                                <Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
                            </DataTemplate.Resources>
                            <TextBlock Text="{Binding Left}" TextAlignment="Center" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Right" Width="50">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <DataTemplate.Resources>
                                <Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
                            </DataTemplate.Resources>
                            <TextBlock Text="{Binding Right}" TextAlignment="Right" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Top" Width="50" DisplayMemberBinding="{Binding Top}" />
            </GridView>
        </ListView.View>
        <ListView.Items>
            <Thickness>1,2,3,4</Thickness>
            <Thickness>5,6,7,8</Thickness>
            <Thickness>9,10</Thickness>
        </ListView.Items>
    </ListView>
</Window>