样式仅适用于 Grid.Resources 之外的第一次出现?

Style only works for the first occurence when outside Grid.Resources?

我有一个带有数据模板的网格视图,其中包含一个切换按钮。 Gridview 中项目的数据模板有一个网格,带有一个程式化的切换按钮。切换按钮的样式位于 Grid.Resources 中。它工作正常,但是当我将样式从 Grid.Resources 移动到 Page.Resources 或 App.xaml 时,样式中定义的按钮内的内容从所有按钮中消失,除了第一次出现网格视图中的按钮。这是样式:

<Style TargetType="ToggleButton" x:Key="teststyle">
        <Setter Property="Padding" Value="0"/>
        <Setter Property="Content">
            <Setter.Value>
                <Path HorizontalAlignment="Center" Stroke="Black" StrokeThickness="1.25"  VerticalAlignment="Center" Height="9" Width="9"  Stretch="Uniform" Fill="Black" Data="M 0,0 -11.78,-11.779 0,-23.561 l 1.061,1.061 -9.97,9.971 21.064,0 0,1.5 -21.064,0 9.97,9.968 L 0,0 Z" RenderTransformOrigin="0.5,0.5" >
                    <Path.RenderTransform>
                        <CompositeTransform Rotation="-90"/>
                    </Path.RenderTransform>
                </Path>
            </Setter.Value>
        </Setter>
</Style>

以下是该行为的屏幕截图:http://imgur.com/a/8iZaD顶部图像是样式位于 Grid.Resources 时的原始图像,底部是样式移动时的图像。

在 XAML 中移动样式的最佳方法是使用 Blend 设计器。

您可以从 Blend 的“资源”部分查看和组织您的样式。之后,您可以将本地样式拖放到 App.xaml 或 Resources.xaml 中。所有参考资料都会自动更新,您可以从下面的gif图片查看。

您可以通过在您的样式中使用 ContentTemplate 而不是 Content 来解决此问题。

<Page.Resources>
    <Style TargetType="ToggleButton">
        <Setter Property="Padding" Value="0"/>
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Path HorizontalAlignment="Center" Stroke="Black" StrokeThickness="1.25"  VerticalAlignment="Center" Height="9" Width="9"  Stretch="Uniform" Fill="Black" Data="M 0,0 -11.78,-11.779 0,-23.561 l 1.061,1.061 -9.97,9.971 21.064,0 0,1.5 -21.064,0 9.97,9.968 L 0,0 Z" RenderTransformOrigin="0.5,0.5" >
                        <Path.RenderTransform>
                            <CompositeTransform Rotation="-90"/>
                        </Path.RenderTransform>
                    </Path>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

Style 可以在您的 DataTemplate 之外工作,这里的问题是 Path 您设置为 ToggleButtonContent

XAML Style 中的资源必须是可共享的(参见 XAML resources must be shareable):

For an object to exist in a ResourceDictionary, that object must be shareable.

Being shareable is required because, when the object tree of an app is constructed and used at run time, objects cannot exist at multiple locations in the tree. Internally, the resource system creates copies of resource values to use in the object graph of your app when each XAML resource is requested.

但是 UIElement 永远无法共享,并且 Path 继承自 UIElement,因此 Path 不可共享。当在 DataTemplate 中设置 Style 并将 Style 放在 DataTemplate 之外时,项目中的每个 ToggleButton 都会应用 Style,但是Path 只能显示一次,因为它不可共享。要测试它,您可以在 Style 中添加一个对象,例如:

<Style x:Key="teststyle" TargetType="ToggleButton">
    <Setter Property="Padding" Value="0" />
    <Setter Property="Content">
        <Setter.Value>
            <Path Width="9"
                  Height="9"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center"
                  Data="M 0,0 -11.78,-11.779 0,-23.561 l 1.061,1.061 -9.97,9.971 21.064,0 0,1.5 -21.064,0 9.97,9.968 L 0,0 Z"
                  Fill="Black"
                  RenderTransformOrigin="0.5,0.5"
                  Stretch="Uniform"
                  Stroke="Black"
                  StrokeThickness="1.25">
                <Path.RenderTransform>
                    <CompositeTransform Rotation="-90" />
                </Path.RenderTransform>
            </Path>
        </Setter.Value>
    </Setter>
    <Setter Property="Background" Value="Red" />
</Style>

然后你会发现你ToggleButton的所有背景都变成了红色。你也可以直接把两个 ToggleButton 放在一个 StackPanel 里,比如:

<StackPanel>
    <ToggleButton Style="{StaticResource teststyle}" />
    <ToggleButton Style="{StaticResource teststyle}" />
</StackPanel>

您也可以找到只有第一个 ToggleButton 有路径。

当你把 Style 放在 DataTemplate 里面时,每个项目都会有自己的 Resources,所以它工作正常。

如果你像@Jean-Sébastien Dupuy 说的那样使用 ContentTemplate,那么 Value 会变成一个 DataTemplate,它是可共享的,因为它源自 FrameworkTemplate , 所以它也能正常工作。