【问题标题】:Set button as selected state and change style将按钮设置为选定状态并更改样式
【发布时间】:2013-04-04 22:31:43
【问题描述】:

这是我的实际按钮样式:

<Style x:Key="CategoryButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid x:Name="grid">
                    <Path x:Name="TabPath" StrokeThickness="2"
                          Margin="{Binding ElementName=buttonContent, Converter={x:Static c:ContentToMarginConverter.Value}}"
                          Stroke="{StaticResource BorderBrush1}"
                          Fill="{StaticResource TabItemPathBrush}">
                        <Path.Data>
                            <PathGeometry>
                                <PathFigure IsClosed="False" StartPoint="1,0" 
                                            Segments="{Binding ElementName=buttonContent, Converter={x:Static c:ContentToPathConverter.Value}}">
                                </PathFigure>
                            </PathGeometry>
                        </Path.Data>
                        <Path.LayoutTransform>
                            <!-- For some reason  -->
                            <ScaleTransform ScaleY="-1"/>
                        </Path.LayoutTransform>
                    </Path>
                    <Rectangle x:Name="TabItemTopBorder" Height="2" Visibility="Visible"
                               VerticalAlignment="Bottom" Fill="{StaticResource BorderBrush1}"
                               Margin="{Binding ElementName=TabPath, Path=Margin}" />
                    <ContentPresenter x:Name="buttonContent" Margin="10,2,10,2" VerticalAlignment="Center"
                                      TextElement.Foreground="{StaticResource ForegroundBrush}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Fill" TargetName="TabPath">
                            <Setter.Value>
                                <SolidColorBrush Color="#FFe4f6fa"/>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="BitmapEffect">
                            <Setter.Value>
                                <DropShadowBitmapEffect Direction="302" Opacity="0.4" 
                                                        ShadowDepth="2" Softness="0.5"/>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" TargetName="grid" Value="0.25"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我需要添加可以将按钮设置为选定状态的代码,类似于按下按钮时的状态。我正在考虑使用 VisualStateManager 但我不确定它是否是好方法以及我该如何做到这一点。我从这样的事情开始:

<VisualStateManager.VisualStateGroups>
     <VisualState x:Name="Normal" />
     <VisualState x:Name="Selected">
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TabPath" 
                                   Storyboard.TargetProperty="Fill">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="#FFe4f6fa" />
             </ObjectAnimationUsingKeyFrames>
         </Storyboard>
     </VisualState>
</VisualStateManager.VisualStateGroups>

但它不起作用。我只是不知道在情节提要中使用什么。

编辑 - 几乎可以工作:

<VisualState x:Name="Selected">
     <Storyboard>
        <ColorAnimation Storyboard.TargetName="TabPath" Storyboard.TargetProperty="Fill.(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" To="#FFe4f6fa" Duration="0:0:0" />
        <ColorAnimation Storyboard.TargetName="TabPath" Storyboard.TargetProperty="Fill.(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" To="#FFa9cde7" Duration="0:0:0" />               
      </Storyboard>
 </VisualState>

忘记添加我的画笔:

<LinearGradientBrush x:Key="TabItemSelectedPathBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="#FFe4f6fa" Offset="0"/>
    <GradientStop Color="#FFa9cde7" Offset="1"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="TabItemPathBrush" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="#FFa9cde7" Offset="0"/>
    <GradientStop Color="#FF3164a5" Offset="1"/>
</LinearGradientBrush>

【问题讨论】:

  • 您的要求不明确。按钮没有Selected 视觉状态,如果要显示已检查状态,可以使用ToggleButton。或者Selected,你的意思是Focused state?
  • 我的意思是我可以定义一些状态,然后通过以下方式将视觉更改为该状态:var bl = VisualStateManager.GoToState(selectedButton, "Activate", true);。它真的不取决于状态的名称(选择,激活,没关系)。

标签: c# wpf button styles visualstatemanager


【解决方案1】:

使用使用相同样式和模板的ToggleButton

按照您的风格(原始问题中的那个)将风格和控制模板上的TargetType 更改为ButtonBase

在控件模板触发器中添加这个触发器:

 <Trigger Property="ToggleButton.IsChecked" Value="True">
     <Setter Property="Fill" TargetName="TabPath">
         <Setter.Value>
             <SolidColorBrush Color="#FFe4f6fa"/>
         </Setter.Value>
     </Setter>
     <Setter Property="BitmapEffect">
         <Setter.Value>
             <DropShadowBitmapEffect Direction="302" Opacity="0.4" ShadowDepth="2" Softness="0.5"/>
         </Setter.Value>
     </Setter>
 </Trigger>

现在您可以将此样式用于按钮、切换按钮、单选按钮和复选框。

【讨论】:

    【解决方案2】:

    VisualStates 应该在ControlTemplate 的根元素上声明。使用以下代码,

            <Grid>
        <Grid.Resources>
            <SolidColorBrush x:Key="FillBrush" Color="Magenta" />
            <Color x:Key="StateBrush" >#a3bfb1</Color>
            <Style x:Key="CategoryButtonStyle" TargetType="{x:Type Button}">
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
    
                <Setter Property="Padding" Value="1"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Border Background="Green" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" x:Name="root">
    
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Selected">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TabPath" 
                                   Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)">
                                                    <DiscreteObjectKeyFrame KeyTime="0"  Value="{StaticResource StateBrush}">
    
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Grid x:Name="grid">
                                    <Path x:Name="TabPath" StrokeThickness="1" 
    
                          Stroke="Blue"
                          Fill="{StaticResource FillBrush}" Canvas.Left="16.75"
              Canvas.Top="14"
              Width="50"
              Height="40"
              Data="F1 M 26.75,24L 16.75,34L 23.5,34L 34,24L 23.5,14L 16.75,14L 26.75,24 Z ">
                                        <Path.LayoutTransform>
                                            <!-- For some reason  -->
                                            <ScaleTransform ScaleY="-1"/>
                                        </Path.LayoutTransform>
                                    </Path>
                                    <ContentPresenter x:Name="buttonContent" Margin="10,2,10,2" VerticalAlignment="Center"
                                      TextElement.Foreground="{TemplateBinding Foreground}"/>
                                </Grid>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    
        </Grid.Resources>
        <Button x:Name="test" Style="{StaticResource CategoryButtonStyle}" Content="Test"  VerticalAlignment="Center" Width="200px" BorderBrush="#888" BorderThickness="1px"/>
    </Grid>
    

    此代码将按预期更改状态。

    VisualStateManager.GoToState(test, "TestState", true);

    根据需要对模板进行更改,但确保将 VisualState 声明放在 ControlTemplate 的 Root 元素中(本例中为 Border

    编辑: 我已经使用正确的属性路径更新了 Selected VisualState 的转换声明。让我知道它是否能解决您的问题。

    【讨论】:

    • 此 TestState 正在工作,但我无法进入更改属性 Fill in Path 的工作状态。
    • @Bibo,路径和值应根据我的编辑指定。检查它是否解决了问题。
    • 谢谢,但我想使用该转换器,因为它会根据按钮内容的长度调整按钮路径的大小。你有什么解决方案可以像我在我的问题中那样使用路径吗?
    • 忽略Path的代码,只需注意VisualState转换中的Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)",您可以使用现有的路径标记。我只是删除了它们进行测试,因为我没有它们的代码。它应该可以正常工作,因为转换器不适用于Fill
    • @Bibo 你能更新一下你在使用转换器时遇到的错误吗?
    【解决方案3】:

    我个人会使用 Blend 来完成这样的任务,它确实是 Visual Studio 开发 WPF 应用程序的伴侣。

    单击几下即可访问它,没有什么能阻止您使用它或将它生成的 XAML 复制到您的项目中。

    编辑按钮样式

    触发器

    这是你所有的按钮状态

    混合就像黄油面包,WPF 更美味,除非你更喜欢纯黄油:-)

    请注意,如果您使用的是 VS2012 并正在处理 WPF 项目,Microsoft Blend + SketchFlow Preview for Visual Studio 2012 是允许您编辑 WPF 项目的版本。与 VS2012 捆绑的版本仅适用于 Windows Store 应用程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-02
      • 2014-08-30
      • 1970-01-01
      • 1970-01-01
      • 2014-12-04
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多