你的位置:首页 > ASP.net教程

[ASP.net教程]【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 是能够继承的。由于没啥技术含量-_-|||,这里就大家自己弄了。