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

[亡魂溺海] 提交于 2019-12-25 05:50:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!