• 【Win10】让 AppBarButton 支持更复杂的 Icon 内容


    最近有一个需求,需要制作这么一个 AppBarButton:

    QQ截图20151102162629

    这个 AppBarButton 的 Icon 是一个评论框图标里面再显示评论数(大于 99 条则显示 99+)。其中评论数是通过数据绑定得来的。

    要单独显示这个评论框图标或者单独显示评论数都不是难题,然而要同时显示这两者就成了一个大问题了,因为 AppBarButton 的 Icon 属性只能设置一个。再看看 Icon 属性的类型,是 IconElement 这个类。但是,这个类的构造函数是内部的,我们也没法继承它。那么,从 Icon 属性上入手是不可能了。

    但是,要注意到,绝大部分的控件都是有模板的,然后可以修改的。对于 AppBarButton,是不是也这样呢?答案是肯定的。

    在 MSDN 上,我们可以查阅到 AppBarButton 的默认样式和模板:https://msdn.microsoft.com/zh-cn/library/windows/apps/mt299105.aspx

    <!-- Default style for Windows.UI.Xaml.Controls.AppBarButton -->
    <Style TargetType="AppBarButton">
      <Setter Property="Background" Value="Transparent"/>
      <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
      <Setter Property="HorizontalAlignment" Value="Left"/>
      <Setter Property="VerticalAlignment" Value="Top"/>
      <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
      <Setter Property="FontWeight" Value="Normal"/>
      <Setter Property="Width" Value="68"/>
      <Setter Property="UseSystemFocusVisuals" Value="True" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="AppBarButton">
            <Grid
                x:Name="Root"
                MinWidth="{TemplateBinding MinWidth}"
                MaxWidth="{TemplateBinding MaxWidth}"
                Background="{TemplateBinding Background}">
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="ApplicationViewStates">
                  <VisualState x:Name="FullSize"/>
                  <VisualState x:Name="Compact">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="Overflow">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="OverflowWithToggleButtons">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" Storyboard.TargetProperty="Margin">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="38,11,0,13"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal">
                    <Storyboard>
                      <PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="PointerOver">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Background">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <PointerUpThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="Pressed">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Background">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <PointerDownThemeAnimation Storyboard.TargetName="OverflowTextLabel" />
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="Disabled">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverflowTextLabel" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
    
              <StackPanel x:Name="ContentRoot" MinHeight="{ThemeResource AppBarThemeCompactHeight}">
                <ContentPresenter
                    x:Name="Content"
                    Height="20"
                    Margin="0,14,0,4"
                    Content="{TemplateBinding Icon}"
                    Foreground="{TemplateBinding Foreground}"
                    HorizontalAlignment="Stretch"
                    AutomationProperties.AccessibilityView="Raw"/>
                <TextBlock
                    x:Name="TextLabel"
                    Text="{TemplateBinding Label}"
                    Foreground="{TemplateBinding Foreground}"
                    FontSize="12"
                    FontFamily="{TemplateBinding FontFamily}"
                    TextAlignment="Center"
                    TextWrapping="Wrap"
                    Margin="0,0,0,6"/>
              </StackPanel>
    
              <TextBlock
                  x:Name="OverflowTextLabel"
                  Text="{TemplateBinding Label}"
                  Foreground="{TemplateBinding Foreground}"
                  FontSize="15"
                  FontFamily="{TemplateBinding FontFamily}"
                  TextAlignment="Left"
                  TextTrimming="Clip"
                  TextWrapping="NoWrap"
                  HorizontalAlignment="Stretch"
                  VerticalAlignment="Center"
                  Margin="12,11,0,13"
                  Visibility="Collapsed"/>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    仔细看一下这个模板,我们可以发现这么一句:

    Content="{TemplateBinding Icon}"

    我们尝试一下将 Icon 修改为 Content。(Content 属性是 AppBarButton 从 Button 类继承得来的,但是 AppBarButton 它自身并没有使用到这个属性。)

    然后编写 XAML 测试下:

    <CommandBar>
        <AppBarButton Style="{StaticResource MyAppBarButtonStyle}"
                                 Label="评论">
            <AppBarButton.Content>
                <Grid>
                    <FontIcon Glyph="&#xE8BD;"
                                     FontFamily="Segoe MDL2 Assets"
                                     HorizontalAlignment="Center"
                                     VerticalAlignment="Center" />
                    <TextBlock Text="99+"
                                       HorizontalAlignment="Center"
                                       VerticalAlignment="Center"
                                       FontSize="9"
                                       RenderTransformOrigin="0.5,0.5">
                        <TextBlock.RenderTransform>
                            <TranslateTransform Y="-2.5" />
                        </TextBlock.RenderTransform>
                    </TextBlock>
                </Grid>
            </AppBarButton.Content>
        </AppBarButton>
    </CommandBar>

    运行后,你应该可以看到文章开头的效果了。

    最后,当然是稍微封装下了,因为 AppBarButton 是能够继承的。由于没啥技术含量-_-|||,这里就大家自己弄了。

  • 相关阅读:
    自动化测试项目实战训练【广州8月】
    RFT基础使用手册
    TestComplete自动化测试实战训练【6月11、12号】
    Jubula Eclipse开源功能测试工具
    网络管理自动化测试应用
    IBM RFT自动化测试实战课程
    GUI自动化测试原理剖析—JAVA测试篇
    简易自动化测试设计之(一) 基于RFT的自动化测试层次
    录制,到底给我们带来了什么?
    IBM Rational Functional Tester(RFT) 自动化测试框架ITCL
  • 原文地址:https://www.cnblogs.com/h82258652/p/4930986.html
Copyright © 2020-2023  润新知