1

I wanna create Close/Maximize/Minimize Buttons for my app. So I wrote this piece of Style:

<Style x:Key="CloseButton" TargetType="Button">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Grid Background="Transparent">
                         <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimation
                                                        Storyboard.TargetName="BackgroundColor1" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
                                                        Duration="0"
                                                        To="#FFFF1111"/>
                                        <ColorAnimation
                                                        Storyboard.TargetName="BackgroundColor2" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
                                                        Duration="0"
                                                        To="#FFFF1111"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Ellipse Name="BackgroundColor1" Margin="4,0,0,0" Width="18" Height="18">
                            <Ellipse.Fill>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                                    <GradientStop Color="{StaticResource ColorBorder}" Offset="0.2"/>
                                    <GradientStop Color="WhiteSmoke" Offset=".9"/>
                                </LinearGradientBrush>
                            </Ellipse.Fill>
                        </Ellipse>
                        <Ellipse Name="BackgroundColor2" Margin="4,0,0,0" Width="18" Height="18">
                            <Ellipse.Stroke>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                                    <GradientStop Color="{StaticResource ColorBorder}" Offset="1"/>
                                    <GradientStop Color="WhiteSmoke" Offset="0"/>
                                </LinearGradientBrush>
                            </Ellipse.Stroke>
                        </Ellipse>

                        <Ellipse Margin="4,0,0,8" Width="7" Height="7">
                            <Ellipse.Fill>
                                <LinearGradientBrush StartPoint="1,0" EndPoint="0,1">
                                    <GradientStop Color="WhiteSmoke" Offset="0"/>
                                    <GradientStop Color="Transparent" Offset="0.7"/>
                                </LinearGradientBrush>
                            </Ellipse.Fill>
                        </Ellipse>

                        <Ellipse Margin="4,0,0,0" Width="18" Height="18" StrokeThickness="2" StrokeLineJoin="Round">
                            <Ellipse.Stroke>
                                <LinearGradientBrush StartPoint="1,0" EndPoint="1,1">
                                    <GradientStop Color="Black" Offset="0"/>
                                    <GradientStop Color="Transparent" Offset="1"/>
                                </LinearGradientBrush>
                            </Ellipse.Stroke>
                        </Ellipse>

                        <Ellipse Margin="4,0,0,0" Width="18" Height="18" StrokeThickness="1" StrokeLineJoin="Round">
                            <Ellipse.Stroke>
                                <LinearGradientBrush StartPoint="1,0" EndPoint="1,1">
                                    <GradientStop Color="#FF333333" Offset="1"/>
                                    <GradientStop Color="Transparent" Offset="0.5"/>
                                </LinearGradientBrush>
                            </Ellipse.Stroke>
                        </Ellipse>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Right now I have 3 duplicate of this Style, With changes in MouseOver color, like this:

<ColorAnimation Storyboard.TargetName="BackgroundColor1" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)"
<!-- Just "To" Color changes is each button -->
To="#FFFF1111"/>

But I wanna just bind this color to Button Background color, So that I don't have to have 3 duplicate Style. I did some RelativeSource Binding but didn't work.

Q1: How can i Bind this Gradient to button Background?
Q2: Is there any other Type of controller that could do this AND have color properties?

Thanks in advance.

Edit: Transition code:

<VisualStateGroup.Transitions>
    <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.2"/>
    <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.2"/>
</VisualStateGroup.Transitions>
Mostafa
  • 103
  • 1
  • 11

1 Answers1

1

If it were me I would probably do it something more like below so you could pass in Brush, Color, ColorName etc easier instead of swap out GradientStop's and just deal with one whole object at a time. Since Fill will only accept Color. Brush and Fill are different beasts. ;)

Something like;

Style;

<Style x:Key="CloseButton2" TargetType="{x:Type Button}">
   <Setter Property="Background" Value="Red"/>
   <Setter Property="HorizontalContentAlignment" Value="Center"/>
   <Setter Property="VerticalContentAlignment" Value="Center"/>
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type Button}">
            <Grid>
               <!-- Left this here in case you want to use it later for something. Just set Visibility. -->
               <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                       Background="{TemplateBinding Background}" SnapsToDevicePixels="true" Visibility="Collapsed">
                  <ContentPresenter x:Name="contentPresenter" Focusable="False"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" 
                                    RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
               </Border>

               <!-- Your new magic. -->
               <Border x:Name="buttonLight" Opacity="0"
                       Background="{TemplateBinding Background}" CornerRadius="50" 
                       Width="18" Height="18" Margin="4,0,0,0"/>


               <Ellipse Name="BackgroundColor1" Margin="4,0,0,0" Width="18" Height="18">
                  <Ellipse.Fill>
                     <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                        <GradientStop Color="Transparent" Offset="0.2"/>
                        <GradientStop Color="WhiteSmoke" Offset=".9"/>
                                    </LinearGradientBrush>
                  </Ellipse.Fill>
               </Ellipse>
               <Ellipse Name="BackgroundColor2" Margin="4,0,0,0" Width="18" Height="18">
                  <Ellipse.Stroke>
                     <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                        <GradientStop Color="Transparent" Offset="1"/>
                        <GradientStop Color="WhiteSmoke" Offset="0"/>
                                    </LinearGradientBrush>
                  </Ellipse.Stroke>
               </Ellipse>
               <Ellipse Margin="4,0,0,8" Width="7" Height="7">
                  <Ellipse.Fill>
                     <LinearGradientBrush StartPoint="1,0" EndPoint="0,1">
                        <GradientStop Color="WhiteSmoke" Offset="0"/>
                        <GradientStop Color="Transparent" Offset="0.7"/>
                                    </LinearGradientBrush>
                  </Ellipse.Fill>
               </Ellipse>
               <Ellipse Margin="4,0,0,0" Width="18" Height="18" StrokeThickness="2" StrokeLineJoin="Round">
                  <Ellipse.Stroke>
                     <LinearGradientBrush StartPoint="1,0" EndPoint="1,1">
                        <GradientStop Color="Black" Offset="0"/>
                        <GradientStop Color="Transparent" Offset="1"/>
                     </LinearGradientBrush>
                  </Ellipse.Stroke>
               </Ellipse>
               <Ellipse Margin="4,0,0,0" Width="18" Height="18" StrokeThickness="1" StrokeLineJoin="Round">
                  <Ellipse.Stroke>
                     <LinearGradientBrush StartPoint="1,0" EndPoint="1,1">
                        <GradientStop Color="#FF333333" Offset="1"/>
                        <GradientStop Color="Transparent" Offset="0.5"/>
                     </LinearGradientBrush>
                  </Ellipse.Stroke>
               </Ellipse>
            </Grid>
            <ControlTemplate.Triggers>

               <Trigger Property="IsMouseOver" Value="true">
                  <Setter Property="Opacity" TargetName="buttonLight" Value="1"/>
               </Trigger>

            </ControlTemplate.Triggers>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

Then, instance examples;

<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">

   <Button Style="{DynamicResource CloseButton2}"/>
   <Button Background="Green" 
           Style="{DynamicResource CloseButton2}" Margin="0,10"/>
   <Button Background="Blue" 
           Style="{DynamicResource CloseButton2}"/>

</StackPanel>

Hope this helps, cheers.

MORE INFORMATION;

You can absolutely still apply your transition, for this; you would just delete the triggers (this part in the previous example);

<!-- DELETE THIS PART -->
    <ControlTemplate.Triggers>

       <Trigger Property="IsMouseOver" Value="true">
          <Setter Property="Opacity" TargetName="buttonLight" Value="1"/>
       </Trigger>

    </ControlTemplate.Triggers>

Then just plop in your VisualStateManager somewhere inside of the Grid which I prefer to do at the top right under the <Grid> tag;

    <!-- Invoke VisualStateManager to handle it instead of Trigger as requested. -->
    <VisualStateManager.VisualStateGroups>
       <VisualStateGroup x:Name="CommonStates">
          <VisualStateGroup.Transitions>
             <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.2"/>
             <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.2"/>
          </VisualStateGroup.Transitions>
          <VisualState x:Name="Normal"/>
          <VisualState x:Name="MouseOver">
             <Storyboard>
                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" 
                                               Storyboard.TargetName="buttonLight"
                                               Duration="0:0:1">
                   <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                </DoubleAnimationUsingKeyFrames>
             </Storyboard>
          </VisualState>
          <VisualState x:Name="Pressed"/>
          <VisualState x:Name="Disabled"/>
       </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

...and that's it, you're done, and still have the color functionalities etc. :)

Chris W.
  • 22,835
  • 3
  • 60
  • 94
  • Thanks! Actually I did something similar with another Ellipse, But I don't know how to set the animation. Is there anything that you can do in your current answer? – Mostafa Sep 07 '16 at 16:33
  • @Mostafa I don't understand why your animation matters if there's not even a transition duration. From what I saw literally all it's doing is turning the hue of the button from one color to another immediately, the same thing accomplished by the simple trigger in this example? So I may need a little more explanation on what you're hoping to accomplish overall. :) – Chris W. Sep 07 '16 at 16:46
  • oops,I forgot to add the Transition code. I'll do it right now – Mostafa Sep 07 '16 at 17:09
  • I didn't even think about working with opacity, That's brilliant, Thank you! – Mostafa Sep 07 '16 at 19:11
  • No worries, there's a bunch of ways to accomplish the same thing, but this way you're not just limited to `Fill` color (although a shape with Fill is always a bit lighter size than a `Border` with `Background` property) but I figured it might be nice to just plop whatever color in there any way you want to do it. Cheers – Chris W. Sep 07 '16 at 19:22