【问题标题】:Binding Shape FillColor to Button BackgroundBrush将形状 FillColor 绑定到按钮 BackgroundBrush
【发布时间】:2017-01-15 05:14:18
【问题描述】:

我想为我的应用创建关闭/最大化/最小化按钮。所以我写了这篇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>

现在我有 3 个重复的这种 Style,随着 MouseOver 颜色的变化,像这样:

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

但我只想将此颜色绑定到按钮 Background 颜色,这样我就不必有 3 个重复的 Style。我做了一些 RelativeSource 绑定,但没有奏效。

Q1:如何将此渐变绑定到按钮背景
Q2:有吗?任何其他 类型 可以做到这一点的控制器 AND 具有颜色属性?

提前致谢。

编辑:转换代码:

<VisualStateGroup.Transitions>
    <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.2"/>
    <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.2"/>
</VisualStateGroup.Transitions>

【问题讨论】:

  • 所以您只需要一个通用按钮样式模板,并且能够在每个实例中将不同的鼠标悬停颜色作为属性传递?
  • @ChrisW。正是!

标签: c# wpf xaml


【解决方案1】:

如果是我,我可能会像下面那样做,这样你就可以更容易地传递 Brush、Color、ColorName 等,而不是换掉 GradientStop 并一次只处理一个完整的对象。因为填充将只接受颜色。 BrushFill 是不同的野兽。 ;)

类似的东西;

风格;

<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>

然后,实例;

<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>

希望这会有所帮助,干杯。

更多信息;

为此,您绝对仍然可以应用您的过渡;您只需删除触发器(前一个示例中的这一部分);

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

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

    </ControlTemplate.Triggers>

然后只需在 Grid 内的某处插入你的 VisualStateManager,我更喜欢在右上角的 &lt;Grid&gt; 标签下执行此操作;

    <!-- 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>

...就是这样,你已经完成了,并且仍然具有颜色功能等:)

【讨论】:

  • 谢谢!实际上我对另一个椭圆做了类似的事情,但我不知道如何设置动画。您当前的答案有什么可以做的吗?
  • @Mostafa 如果甚至没有过渡持续时间,我不明白为什么你的动画很重要。从字面上看,它所做的就是立即将按钮的色调从一种颜色变为另一种颜色,这与本示例中的简单触发器完成的相同吗?因此,我可能需要对您希望整体完成的工作进行更多解释。 :)
  • 哎呀,我忘了添加转换代码。我马上就做
  • 我什至没有考虑过使用不透明度,太棒了,谢谢!
  • 别担心,有很多方法可以完成同样的事情,但这样你就不仅仅局限于Fill 颜色(尽管带有填充的形状总是比BorderBackground 属性),但我认为将任何颜色放入其中可能会很好。干杯
猜你喜欢
  • 1970-01-01
  • 2016-07-27
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多