问题
I have a gridview with a data template which includes a togglebutton. The datatemplate for the items in the Gridview has a grid in it, with a stylized togglebutton. The style for the togglebutton is located in Grid.Resources. It works fine, but when I move the style from Grid.Resources to either Page.Resources or App.xaml, the content inside the button that is defined in the style disappears from all except the first occurrence of the button in the gridview. Here is the style:
<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>
Here are screenshots of the behavior: http://imgur.com/a/8iZaD The top image is the original one when the style was located in Grid.Resources, and the bottom is when the style gets moved.
回答1:
You can workaround this behavior by using ContentTemplate in your style instead 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>
回答2:
Style
can work outside your DataTemplate
, the problem here is the Path
you've set as the Content
of your ToggleButton
.
XAML resources in Style
must be shareable (See 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.
But UIElement
can never be shareable and Path
inherits from UIElement
so Path
is not shareable. When setting your Style
in DataTemplate
and putting the Style
outside the DataTemplate
, every ToggleButton
in the items do apply the Style
, but the Path
can only displays once as it's not shareable. To test it, you can add a object in your Style
like:
<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>
Then you will find all the backgrounds of your ToggleButton
become red. Also you can directly put two ToggleButton
in a StackPanel
like:
<StackPanel>
<ToggleButton Style="{StaticResource teststyle}" />
<ToggleButton Style="{StaticResource teststyle}" />
</StackPanel>
You can also find only the first ToggleButton
have the path.
And when you put the Style
inside DataTemplate
, every item will has its own Resources
, so it works fine.
If you use ContentTemplate
like @Jean-Sébastien Dupuy said, then the Value
become a DataTemplate
which is shareable as it's derived from FrameworkTemplate
, so it also works fine.
回答3:
Best way to move your styles in XAML is using Blend designer.
You can view and organize your styles from Resources section in Blend. After that you can drag and drop your local style into App.xaml or Resources.xaml. All references will be updated automatically, you can check from below gif image.
来源:https://stackoverflow.com/questions/34516617/style-only-works-for-the-first-occurence-when-outside-grid-resources