zoukankan      html  css  js  c++  java
  • 【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 是能够继承的。由于没啥技术含量-_-|||,这里就大家自己弄了。

  • 相关阅读:
    MFC中char*,string和CString之间的转换(待补充)
    Gem/Bundle/Rvm
    Ruby开发入门
    Maven原型骨架及常见问题
    Nginx Upstream模块源码分析(上)
    mysqldump的几个主要选项探究
    探索Antlr(Antlr 3.0更新版)
    Maven2插件开发入门
    说说家乡的互联网-沈阳
    Nginx模块之SessionSticky
  • 原文地址:https://www.cnblogs.com/h82258652/p/4930986.html
Copyright © 2011-2022 走看看