代码改变世界

ComponentOne C1ToolbarToggleButton Style

2012-11-29 23:01  gitenius  阅读(781)  评论(1编辑  收藏  举报

本文主要介绍 C1ToolbarToggleButton Control 的样式修改。

本文分为以下几个部分:

一:Outer Border 和 Inner Border 对布局及视觉效果的影响

二:C1ToolbarToggleButton 元素布局

第一部分:视觉状态管理器(VisualStateManager)

第二部分:视觉树(Visual Tree)

第三部分:CommonStates静态分析

第四部分: Resources And Binding:(Default Style)

第五部分:视觉状态切换(VisualStateGroup.Transitions)

三:自定义按钮示例

 

一:Outer Border 和 Inner Border 对布局及视觉效果的影响

源码BorderLayout.xaml:(注意<Border>的Margin属性和Background的属性

<StackPanel >
        <!-- Example1: InnerBorder.Background=Transparent Margin=0 -->
        <TextBlock Text="Example 1" />
        <Border Tag="OuterBorder" Background="Orange" Width="132" Height="20">
            <Border Tag="InnerBorder" BorderBrush="Green" BorderThickness="2" Margin="0" Background="Transparent"/>
        </Border>        
        <Border Height="20"/>        
        
        <!-- Example2: InnerBorder.Background=Red Margin=0  -->
        <TextBlock Text="Example 2" />
        <Border Tag="OuterBorder" Background="Orange" Width="132" Height="20">
            <Border Tag="InnerBorder"  BorderBrush="Green" BorderThickness="2" Margin="0" Background="Red"/>
        </Border>
        <Border Height="20"/>        
        
        <!-- Example3: InnerBorder.Background=Transparent Margin=5 -->
        <TextBlock Text="Example 3" />
        <Border Tag="OuterBorder" Background="Orange" Width="132" Height="20">
            <Border Tag="InnerBorder"  BorderBrush="Green" BorderThickness="2" Margin="5" Background="Transparent"/>
        </Border>        
        <Border Height="20"/>
                
        <!-- Example4: InnerBorder.Background=Green Margin=5 -->
        <TextBlock Text="Example 4" />
        <Border Tag="OuterBorder" Background="Orange" Width="132" Height="20">
            <Border Tag="InnerBorder" BorderBrush="Green" BorderThickness="2" Margin="5" Background="Red"/>
        </Border>
        
    </StackPanel>

Border元素嵌套属性区别:

  OuterBorder InnerBorder Image
Example 1 Background="Orange" BorderBrush="Green"
BorderThickness="2"
Margin="0"
Background="Transparent"
example1(图1)
Example 2 Background="Orange" BorderBrush="Green"
BorderThickness="2"
Margin="0"
Background="Red"
example2(图2)

注意 :与Example 1相比 , Example 2 的 InnerBorder的  Red 背景 “完全遮挡” OuterBorder 的Orange 背景 原因是Background属性(默认值为Transparent)
Example 3 Background="Orange" BorderBrush="Green"
BorderThickness="2"
Margin="5"
Background="Transparent"
example3(图3)
Example 4 Background="Orange" BorderBrush="Green"
BorderThickness="2"
Margin="5"
Background="Red"
example4(图4)
注意 :与Example 2 相比  Example 4 的 InnerBorder的  Red 背景 “部分遮挡” OuterBorder 的Orange 背景,原因是Margin属性(默认值是0)

视觉效果对比图(5):

example

                  (图5)

二:C1ToolbarToggleButton 元素布局

安装开发工具:Expression Blend 4  和 ComponentOne for Silverlight / ComponentOne for WPF  控件。

Expression Blend 4 官方网站:http://www.microsoft.com/china/expression/

ComponentOne 官方网站:http://our.componentone.com/

使用EB4编辑Button的模版,如图(6)所示:

editTemplate

                                                                                                                                    图(6)

下面参考并讲解源文件ButtonStyle.xaml(分析C1ToolbarToggleButton的布局系统)

第一部分:视觉状态管理器(VisualStateManager)

CommandStates包含Normal,MouseOver,Pressed,Disabled四种视觉状态

CheckStates包含Unchecked,Checked,Indeterminate三种视觉状态

FocusStates包含Unfocused,Focused两种视觉状态

ToolbarStates包含Large,Medium,Small三种视觉状态

由此可见:C1ToolbarToggleButton控件稍微复杂一些,如图(7)所示

vsm

                                  图(7)

第二部分:视觉树(Visual Tree)

元素的视觉树,如图(8)所示

VisualTree

                                                      图(8)

注意元素的排列顺序:BackgroundElement《MouseOverElement《PressedElement《CheckedElement《Grid《DisabledVisualElement(“A《B”表示A元素在B元素下边)

第三部分:CommonStates静态分析

CommonStates的四种视觉状态:(视觉效果与第一部分的Outer Border,Inner Border类似。Outer Border显示为背景色,Inner Border 显示边框颜色)

所以可以通过修改 BackgroudElement元素的外观来修改 C1ToolbarToggleButton的按钮外观(即修改Border的样式)

<!-- Normal 元素 -->
<Border x:Name="BackgroundElement" Background="{Binding Output, ElementName=BackgroundBrush}">
    <Border BorderBrush="{Binding Output, ElementName=InnerBorderBrush}" 
BorderThickness="{StaticResource InnerBorderThickness}"/>
</Border>
<!-- MouseOver 元素 -->
<Border x:Name="MouseOverElement" Background="{Binding Output, ElementName=MouseOverBrush}" Visibility="Collapsed">
    <Border BorderBrush="{Binding Output, ElementName=InnerBorderMouseOverBrush}" 
BorderThickness="{StaticResource InnerBorderThickness}"/>
</Border>
<!-- PressedElement 元素 -->
<Border x:Name="PressedElement" BorderBrush="{TemplateBinding PressedBrush}" 
Background="{Binding Output, ElementName=PressedBrush}" Visibility="Collapsed">
    <Border BorderBrush="{Binding Output, ElementName=InnerBorderPressedBrush}" 
BorderThickness="{StaticResource InnerBorderThickness}"/>
</Border>
<!-- Checked 元素 -->
<Border x:Name="CheckedElement" Background="{Binding Output, ElementName=CheckedBrush}" Visibility="Collapsed"/>
<!-- ContentPresenter  -->
<Grid Margin="{TemplateBinding Padding}">
     <StackPanel x:Name="LargeView" 
DataContext="{Binding Converter={StaticResource commandConverter}, RelativeSource={RelativeSource TemplatedParent}}" 
Margin="{TemplateBinding Padding}">
         <Image x:Name="img1" Source="{Binding LargeImageSource}" Stretch="None"/>
         <TextBlock x:Name="LargeText" TextAlignment="Center" Text="{Binding LabelTitle}"/>
     </StackPanel>
     <StackPanel x:Name="MediumView" 
           DataContext="{Binding Converter={StaticResource commandConverter}, RelativeSource={RelativeSource TemplatedParent}}" 
           Margin="{TemplateBinding Padding}" Orientation="Horizontal" Visibility="Collapsed">
           <Image x:Name="img2" Source="{Binding SmallImageSource}" Stretch="None"/>
           <TextBlock x:Name="MediumText" Text="{Binding LabelTitle}" VerticalAlignment="Center"/>
     </StackPanel>
     <StackPanel x:Name="SmallView" 
           DataContext="{Binding Converter={StaticResource commandConverter}, RelativeSource={RelativeSource TemplatedParent}}" 
           Margin="{TemplateBinding Padding}" Orientation="Horizontal" Visibility="Collapsed">
           <Image x:Name="img3" Source="{Binding SmallImageSource}" Stretch="None"/>
     </StackPanel>
     <ContentPresenter x:Name="contentPresenter" 
ContentTemplate="{TemplateBinding ContentTemplate}" 
                       Content="{TemplateBinding Content}" 
                       HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                       VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<!-- Disabled 元素 -->
<Border x:Name="DisabledVisualElement" Background="{StaticResource DisabledBrush}" 
        IsHitTestVisible="False" Visibility="Collapsed"/>

C1ToolbarToggleButton的Normal,MouseOver,Pressed,Disabled四种状态对比图(9):

FourState

                                                      图(9)

注意OuterBorder .Background和 InnerBorder.BorderBrush的变化,这里使用了资源绑定

以上是使用默认资源样式的效果图,修改相应的资源可以达到修改按钮颜色的效果,比如金属色,半透明按钮等

第四部分: Resources And Binding:(Default Style)

Source Code:

                            <!-- Normal 元素 绑定资源 Template中定义-->
                            <c1:C1BrushBuilder x:Name="BackgroundBrush" 
                                               DesignBrush="{StaticResource GeneralGradientBrush}" 
                                               DesignColor="{StaticResource BaseColor}" 
                                               Input="{TemplateBinding Background}"/>
                            <c1:C1BrushBuilder x:Name="InnerBorderBrush" 
                                               DesignBrush="{StaticResource InnerBorderBrush}" 
                                               DesignColor="{StaticResource BaseColor}" 
                                               Input="{TemplateBinding Background}"/>

                         
                            <!-- MouseOver 元素 绑定资源 Template中定义-->
                            <c1:C1BrushBuilder x:Name="MouseOverBrush" 
                                               DesignBrush="{StaticResource GeneralGradientOverBrush}" 
                                               DesignColor="{StaticResource MouseOverColor}" 
                                               Input="{TemplateBinding MouseOverBrush}"/>
                            <c1:C1BrushBuilder x:Name="InnerBorderMouseOverBrush" 
                                               DesignBrush="{StaticResource InnerBorderMouseOverBrush}" 
                                               DesignColor="{StaticResource MouseOverColor}" 
                                               Input="{TemplateBinding MouseOverBrush}"/>
                            <!-- PressedElement 元素 绑定资源 Template中定义-->
                            <c1:C1BrushBuilder x:Name="PressedBrush" 
                                               DesignBrush="{StaticResource GeneralGradientSelectedBackground}" 
                                               DesignColor="{StaticResource SelectedColor}" 
                                               Input="{TemplateBinding PressedBrush}"/>
                            <c1:C1BrushBuilder x:Name="InnerBorderPressedBrush" 
                                               DesignBrush="{StaticResource InnerBorderPressedBrush}" 
                                               DesignColor="{StaticResource SelectedColor}" 
                                               Input="{TemplateBinding PressedBrush}"/>

                            <!-- Checked 元素 绑定资源 Template中定义-->
                            <c1:C1BrushBuilder x:Name="CheckedBrush" 
                                               DesignBrush="{StaticResource GeneralGradientCheckedBrush}" 
                                               DesignColor="{StaticResource SelectedColor}" 
                                               Input="{TemplateBinding PressedBrush}"/>
                            
        <!-- Disabled 元素 绑定资源 UserControl.Resource中定义-->
        <SolidColorBrush x:Key="DisabledBrush" Color="#A5FFFFFF"/>
        
        <!-- C1ToolbarToggleButton的Padding属性值 -->
        <Thickness x:Key="ToolbarButtonPadding">2</Thickness>
        
        <!-- InnerBorder 的BorderThickness属性值 -->
        <Thickness x:Key="InnerBorderThickness">1</Thickness>
        
        <!--Normal , MouseOver , Pressed 状态下 OuterBorder的Background属性值 -->
        <LinearGradientBrush x:Key="GeneralGradientBrush" EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FFFAFBFC" Offset="0"/>
            <GradientStop Color="#FFD1DCE8" Offset="1"/>
        </LinearGradientBrush>    
        <LinearGradientBrush x:Key="GeneralGradientOverBrush" EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FFDCEEF3" Offset="0"/>
            <GradientStop Color="#FFC5E3ED" Offset="1"/>
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="GeneralGradientSelectedBackground" EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FFC6E5F0" Offset="0"/>
            <GradientStop Color="#FFA8D4E3" Offset="1"/>
        </LinearGradientBrush>
        
        <!-- Normal , MouseOver , Pressed 状态下 OuterBorder,InnerBorder的DesignColor属性值-->
        <Color x:Key="BaseColor">#FFD1DCE8</Color>
        <Color x:Key="MouseOverColor">#FFBFE1EA</Color>
        <Color x:Key="SelectedColor">#FF8ED1E2</Color>
        
        <!-- Normal ,MouseOver,Pressed ,Checked 状态下 InnerBorder 的BorderBrush属性值 -->
        <SolidColorBrush x:Key="InnerBorderBrush" Color="#FFFAFBFC"/>
        <SolidColorBrush x:Key="InnerBorderMouseOverBrush" Color="#FFFAFBFC"/>
        <SolidColorBrush x:Key="InnerBorderPressedBrush" Color="#FFFAFBFC"/>        
        <SolidColorBrush x:Key="GeneralGradientCheckedBrush" Color="#FF8ED1E2"/>

        <!-- 详见C1ToolbarCommandConverter类,用于绑定上下文 -->
        <c1:C1ToolbarCommandConverter x:Key="commandConverter"/>

具体效果请参考图(10)

Resource

                                                      图(10)

Binding部分:

1.以BackgroundElement为例

<c1:C1BrushBuilder  x:Name="BackgroundBrush"  
                                               DesignBrush="{StaticResource  GeneralGradientBrush}"  
                                               DesignColor="{StaticResource  BaseColor}"  
                                               Input="{TemplateBinding  Background}"/>    
<!-- Normal 元素 -->
                            <Border x:Name="BackgroundElement" 
                                    Background="{Binding Output, ElementName=BackgroundBrush}">
                                <Border BorderBrush="{Binding Output, ElementName=InnerBorderBrush}" 
                                        BorderThickness="{StaticResource InnerBorderThickness}"/>
                            </Border>

BackgroundElement元素的Background绑定包BackgroundBrush元素上,Path=Output

2.以LargeView为例

<StackPanel x:Name="LargeView" 
      DataContext="{Binding Converter={StaticResource commandConverter}, RelativeSource={RelativeSource TemplatedParent}}" 
      Margin="{TemplateBinding Padding}">
      <Image x:Name="img1" Source="{Binding LargeImageSource}" Stretch="None"/>
      <TextBlock x:Name="LargeText" TextAlignment="Center" Text="{Binding LabelTitle}"/>
</StackPanel>

通过绑定使LargeView的DataContext设置为其父元素,由于上下文在VisualTree上的传递,最终达到C1ToolbarToggleButton本身。

所以Margin属性绑定到Padding属性,img1.Source绑定到LargeImageSource属性,LargeText.Text绑定到LabelTitle属性

附注:关于绑定的详细信息,不妨参考《深入浅出WPF》相关章节(便于理解较难的概念)

第五部分:视觉状态切换(VisualStateGroup.Transitions)

上面介绍了C1ToolbarToggleButton的Normal,MouseOver,Pressed,Disabled四种状态图,

现在讲解Normal-〉MouseOver的过程:

在CommonStates视觉状态组中,查看MouseOver状态,通过鼠标所在位置判断,启动StoryBoard,改变MouseOverElement.Visibility=Visible,改变状态为MouseOver。

                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="MouseOver">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Duration="0" 
                                                                           Storyboard.TargetProperty="(UIElement.Visibility)" 
                                                                           Storyboard.TargetName="MouseOverElement">
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>

MouseOver->Pressed,Pressed->Normal等等状态同上,均是通过修改Visibility属性值来改变状态。

请注意Disabled状态:DisabledVisualElement位置为7,参考图(8),即DisabledVisualElement为最上层元素,IsEnabled=True时,颜色为半透明

三:自定义按钮示例

按钮样式一(共享源码):

修改的最主要的代码:

                            <Border x:Name="BackgroundElement" Background="{Binding Output, ElementName=BackgroundBrush}">
                                <Border >
                                    <Border.Background>
                                        <ImageBrush ImageSource="BtnBorder.png"/>
                                    </Border.Background>
                                </Border>
                            </Border>

效果图(11)

s

                                          图(11)

按钮样式二(暂不共享源码,若需要请给我发邮件)

                                         图(12)

本示例代码下载([November 29 2012]C1ToolbarToggleButtonStyle.zip):https://skydrive.live.com/?cid=B53A8D0EF3B97142&id=B53A8D0EF3B97142!110