Click here to Skip to main content
15,884,473 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm trying to define a hierarchy of button styles and I'd like to be able to set property values in the derived style without losing the Content value set in a parent Style.

What I have tried:

Here's the simplified "root" Style:
XML
<Style x:Key="CircleButtonStyle"
       TargetType="{x:Type Button}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid>
          <Ellipse x:Name="Circle"
                   StrokeThickness="0"
                   Stretch="Uniform"
                   Fill="{StaticResource myCustomBrush}" />
          <ContentPresenter HorizontalAlignment="Stretch"
                            VerticalAlignment="Stretch" />
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Here's the simplified first derived style:
XML
<Style x:Key="CircleCrossStyle"
       TargetType="{x:Type Button}"
       BasedOn="{StaticResource CircleButtonStyle}">
  <Setter Property="Content">
    <Setter.Value>
        <Grid>
          <Path Stroke="White"
                Stretch="Uniform"
                Margin="0.5"
                Data="M 1 1 H 0 M 1 1 H 2 M 1 1 V 0 M 1 1 V 2"
                VerticalAlignment="Stretch"
                HorizontalAlignment="Stretch" />
        </Grid>
    </Setter.Value>
  </Setter>
</Style>

The above worked. Now I want to have a Style that is the same except for rotating the whole thing 45°. I tried:
XML
<Style x:Key="CircleXStyle"
       TargetType="{x:Type Button}"
       BasedOn="{StaticResource CircleCrossStyle}">
  <Setter Property="RenderTransformOrigin"
          Value="0.5,0.5" />
  <Setter Property="RenderTransform">
    <Setter.Value>
      <RotateTransform Angle="45" />
    </Setter.Value>
  </Setter>
</Style>

I'm not sure why this didn't work, but it didn't show the Path at all.
I removed the Setters and using this Style still didn't show the Path.

How do I preserve/propagate the Content set in the CircleCrossStyle so I can add the rotation effect in the CircleXStyle? (Or is it impossible using only Styles?)

More exploring:
I was using this on a button in a DataGridTemplateColumn.CellTemplate. I tried referencing the CircleCrossStyle instead. This Style is also used on a button below the DataGrid. When I did this, the CircleCrossStyle was correctly used only on the last row of the grid! And the other button that used the style now showed with the path missing, like all of the other rows of the DataGrid!
I changed the style back to CircleXStyle with no Setters and it behaved exactly the same. Only the last row had the CircleCrossStyle and the other button had only the circle. (I hadn't noticed this before, apparently.)
I tried copying the same Content Setter from CircleCrossStyle to CircleXStyle and changed it to derive from CircleButtonStyle. (So it is identical to CircleCrossStyle except for the name.) Again, only the last row of the Grid is correct.

Any thoughts?
Posted
Updated 3-Nov-16 9:09am
v2
Comments
Richard Deeming 3-Nov-16 14:11pm    
I'm struggling to reproduce the problem in Kaxaml[^]. Both the circle and the path are visible in a button using the CircleXStyle style.

Have you tried using Mole[^] to inspect the logical tree, to see if the content is there but not visible for some reason?
Matt T Heffron 3-Nov-16 14:17pm    
See my update. It appears it may only work ONCE.
Richard Deeming 3-Nov-16 14:25pm    
What happens if you try setting the ContentTemplate instead of the Content?

<Setter Property="ContentTemplate">
    <Setter.Value>
        <DataTemplate>
            <Grid>
                ...
            </Grid>
        </DataTemplate>
    </Setter.Value>
</Setter>
Matt T Heffron 3-Nov-16 14:29pm    
That's the trick!
Thanks!!!
Matt T Heffron 3-Nov-16 14:25pm    
Is the Setter somehow trying to cache the Path as Content and only able to use it in one place?
Is there a way to use the Template property's ControlTemplate in each Style to set the Content of the parent Style?
Is there a way to have a ControlTemplate that is "based on" another ControlTemplate directly to allow setting the Content for "multiple use"?

1 solution

As mentioned in the comments, I suspect the controls added to the Content can only be used in one place.

The solution is to use the ContentTemplate instead, which creates a new instance of the child controls each time it's used.
XML
<Setter Property="ContentTemplate">
    <Setter.Value>
        <DataTemplate>
            <Grid>
                <Path 
                    Stroke="White"
                    Stretch="Uniform"
                    Margin="0.5"
                    Data="M 1 1 H 0 M 1 1 H 2 M 1 1 V 0 M 1 1 V 2"
                    VerticalAlignment="Stretch"
                    HorizontalAlignment="Stretch" 
                />
            </Grid>
        </DataTemplate>
    </Setter.Value>
</Setter>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900