【问题标题】:Make conditional style changes w/o triggers进行不带触发器的条件样式更改
【发布时间】:2016-02-01 22:43:25
【问题描述】:

我是第一次尝试使用 AppBar,但在理解如何在风格上做我希望 AppBar 做的事情时遇到了一些困难。

以下是我定义的一些数据模板,以便我可以在 AppBar 内的按钮上使用图标。我不喜欢股票AppBarButton,因为它将按钮和图标堆叠在一起。我无法看到让它们水平堆叠,所以我只使用了自定义按钮模板。

<DataTemplate x:Key="NewFolderIconTemplate">
    <Path Data="M10,4L12,6H20A2,2 0 0,1 22,8V18A2,2 0 0,1 20,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10M15,9V12H12V14H15V17H17V14H20V12H17V9H15Z"
            Fill="Black" 
            HorizontalAlignment="Stretch"
            VerticalAlignment="Center"
            Width="24"
            Height="24"
            Margin="0 0 10 0"/>
</DataTemplate>
<DataTemplate x:Key="RefreshIconTemplate">
    <Path Data="M19,12H22.32L17.37,16.95L12.42,12H16.97C17,10.46 16.42,8.93 15.24,7.75C12.9,5.41 9.1,5.41 6.76,7.75C4.42,10.09 4.42,13.9 6.76,16.24C8.6,18.08 11.36,18.47 13.58,17.41L15.05,18.88C12,20.69 8,20.29 5.34,17.65C2.22,14.53 2.23,9.47 5.35,6.35C8.5,3.22 13.53,3.21 16.66,6.34C18.22,7.9 19,9.95 19,12Z"
            Fill="Black" 
            HorizontalAlignment="Stretch"
            VerticalAlignment="Center"
            Width="24"
            Height="24"
            Margin="0 0 10 0"/>
</DataTemplate>
<DataTemplate x:Key="SortingIconTemplate">
    <Path Data="M9.25,5L12.5,1.75L15.75,5H9.25M15.75,19L12.5,22.25L9.25,19H15.75M8.89,14.3H6L5.28,17H2.91L6,7H9L12.13,17H9.67L8.89,14.3M6.33,12.68H8.56L7.93,10.56L7.67,9.59L7.42,8.63H7.39L7.17,9.6L6.93,10.58L6.33,12.68M13.05,17V15.74L17.8,8.97V8.91H13.5V7H20.73V8.34L16.09,15V15.08H20.8V17H13.05Z"
            Fill="Black" 
            HorizontalAlignment="Stretch"
            VerticalAlignment="Center"
            Width="24"
            Height="24"
            Margin="0 0 10 0"/>
</DataTemplate>

接下来是实际的 AppBar。我在垂直堆栈面板中放置了一系列按钮,并将堆栈面板放在应用栏内,以便获得垂直菜单效果。

<Page.TopAppBar>
    <AppBar HorizontalAlignment="Right"
            Background="Transparent">

        <AppBar.Resources>
            <Style TargetType="Button"
                   x:Key="AppBarButton">
                <Setter Property="HorizontalAlignment"
                        Value="Stretch" />
                <Setter Property="Background"
                        Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
                <Setter Property="HorizontalContentAlignment"
                        Value="Left" />
            </Style>
        </AppBar.Resources>

        <StackPanel HorizontalAlignment="Right">
            <Button Command="{Binding Path=RefreshDirectoryListCommand}"
                    Style="{StaticResource AppBarButton}">
                <StackPanel Orientation="Horizontal">
                    <ContentControl ContentTemplate="{StaticResource RefreshIconTemplate}"
                                    VerticalAlignment="Center"
                                    Margin="0 0 10 0"/>
                    <TextBlock Text="Refresh" />
                </StackPanel>
            </Button>
            <Button Command="{Binding Path=CreateNewFolderCommand}"
                    Style="{StaticResource AppBarButton}">
                <StackPanel Orientation="Horizontal">
                    <ContentControl ContentTemplate="{StaticResource NewFolderIconTemplate}"
                                    VerticalAlignment="Center"
                                    Margin="0 0 10 0"/>
                    <TextBlock Text="New Folder" />
                </StackPanel>
            </Button>
            <Button Command="{Binding Path=SortListCommand}"
                    Style="{StaticResource AppBarButton}">
                <StackPanel Orientation="Horizontal">
                    <ContentControl ContentTemplate="{StaticResource SortingIconTemplate}"
                                    VerticalAlignment="Center"
                                    Margin="0 0 10 0"/>
                    <TextBlock Text="Sort" />
                </StackPanel>
            </Button>
        </StackPanel>
    </AppBar>
</Page.TopAppBar>

我正在尝试解决一些问题。

  1. AppBar 的内容会在 AppBar 旁边弹出,而不是在它下方,就像下拉菜单一样。有没有办法配置 AppPBar 以这种方式运行,还是我必须设置自定义控件模板的样式?

  1. 当我将鼠标悬停在它们上面时,会呈现边框。 UWP 应用似乎不再有触发器,那么更改鼠标悬停外观的最佳方法是什么?我仍然可以通过样式来完成,还是必须替换控件模板?

  1. 在我的 AppBar 中选择一个按钮会导致该按钮变为半透明状态,从而允许其下方的内容渗入。设置此样式的最佳方式是什么?我想保留模糊动画,并删除透明度:/

  1. AppBar 本身的背景设置为白色,但是当我将鼠标悬停在它上面时,背景是灰色的。我想一旦我知道如何解决类似的边框问题和按钮上的透明度问题,这个问题就可以解决。

这似乎更像是我不知道如何在缺少触发器的情况下正确设置样式的问题。其他人通常会做什么来实现这些影响,构建自定义控制模板?如果是这样,Microsoft 是否为原始模板提供 XAML,以便您不必 100% 从头开始​​?

【问题讨论】:

    标签: xaml winrt-xaml win-universal-app uwp


    【解决方案1】:

    是的,通常我们需要使用自定义控件模板来实现这些效果。 Microsoft 为默认模板提供了 XAML 代码,您可以在 Default control styles and templates 找到它们。同样在 Visual Studio 中,打开 Document Outline 视图,选择要编辑的控件并右键单击,然后选择“Edit Template”选项,然后选择“Edit a cpoy ...”。在此之后,您可以在您选择的位置看到默认模板。默认情况下,它在您的&lt;Page.Resources&gt; 中。这里需要AppBarButton的模板。

    1. 有没有办法配置 AppPBar 以这种方式运行,或者我必须设置自定义控件模板的样式?

      AppBar的模板中,我们可以看到如下代码:

      <Grid x:Name="ContentRoot" ... >
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="*"/>
              <ColumnDefinition Width="Auto"/>
          </Grid.ColumnDefinitions>
          ...
          <ContentControl x:Name="ContentControl" ... />
          <Button x:Name="ExpandButton" Grid.Column="1" ... >
          ...
      <Grid>
      

      所以默认情况下AppBar 的内容显示在“展开按钮”的左侧。如果您希望它显示在“ExpandButton”下,您需要将其模板完全重写为您自己的模板。

    2. UWP 应用似乎不再有触发器,那么更改鼠标悬停外观的最佳方法是什么?

      在 UWP 中,我们使用VisualState 而不是触发器来更改控件在不同状态下的视觉外观。在Button的模板中,有如下代码:

      <VisualState x:Name="PointerOver">
          <Storyboard>
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                  Storyboard.TargetProperty="BorderBrush">
                  <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
              </ObjectAnimationUsingKeyFrames>
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
              Storyboard.TargetProperty="Foreground">
                  <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
              </ObjectAnimationUsingKeyFrames>
              <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
          </Storyboard>
      </VisualState>
      <VisualState x:Name="Pressed">
          <Storyboard>
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
              Storyboard.TargetProperty="Background">
                  <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
              </ObjectAnimationUsingKeyFrames>
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
              Storyboard.TargetProperty="BorderBrush">
                  <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
              </ObjectAnimationUsingKeyFrames>
              <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
              Storyboard.TargetProperty="Foreground">
                  <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
              </ObjectAnimationUsingKeyFrames>
              <PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
          </Storyboard>
      </VisualState>
      

      鼠标悬停时要移除边框,我们可以移除

      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
          Storyboard.TargetProperty="BorderBrush">
          <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
      </ObjectAnimationUsingKeyFrames>
      

      来自 “PointerOver” VisualState

    3. 设置样式的最佳方式是什么?我想保留模糊动画,并删除透明度。

      同样我们可以改变

      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
                                  Storyboard.TargetProperty="Background">
          <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
      </ObjectAnimationUsingKeyFrames>
      

      “按下” VisualState 移除透明度。

    4. 我想一旦我知道如何解决类似的边框问题和按钮上的透明度问题,这个问题就可以解决。

      是的,这是按钮上的类似问题。 “ExpandButton”的样式如下:

      <Style x:Key="EllipsisButton" TargetType="Button">
          <Setter Property="Background" Value="Transparent"/>
          <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
          <Setter Property="BorderThickness" Value="0"/>
          <Setter Property="Padding" Value="0,0,9,0"/>
          <Setter Property="HorizontalAlignment" Value="Stretch"/>
          <Setter Property="HorizontalContentAlignment" Value="Right"/>
          <Setter Property="VerticalAlignment" Value="Stretch"/>
          <Setter Property="VerticalContentAlignment" Value="Top"/>
          <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
          <Setter Property="FontWeight" Value="SemiBold"/>
          <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
          <Setter Property="Width" Value="{ThemeResource AppBarExpandButtonThemeWidth}"/>
          <Setter Property="UseSystemFocusVisuals" Value="True"/>
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="Button">
                      <Grid>
                          <VisualStateManager.VisualStateGroups>
                              <VisualStateGroup x:Name="CommonStates">
                                  <VisualState x:Name="Normal"/>
                                  <VisualState x:Name="PointerOver">
                                      <Storyboard>
                                          <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentPresenter">
                                              <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}"/>
                                          </ObjectAnimationUsingKeyFrames>
                                          <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                              <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
                                          </ObjectAnimationUsingKeyFrames>
                                      </Storyboard>
                                  </VisualState>
                                  <VisualState x:Name="Pressed">
                                      <Storyboard>
                                          <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentPresenter">
                                              <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}"/>
                                          </ObjectAnimationUsingKeyFrames>
                                      </Storyboard>
                                  </VisualState>
                                  <VisualState x:Name="Disabled">
                                      <Storyboard>
                                          <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                              <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
                                          </ObjectAnimationUsingKeyFrames>
                                      </Storyboard>
                                  </VisualState>
                              </VisualStateGroup>
                          </VisualStateManager.VisualStateGroups>
                          <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                      </Grid>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>
      

      您还需要更改 "PointerOver" VisualState 中的 Background。但请注意,如果您的样式在&lt;Page.Resources&gt; 中定义,您需要将此样式的键更改为“MyEllipsisButton”之类的其他内容,并在AppBar 的模板中将此新样式设置为名为“EllipsisButton”的Button,否则AppBar 仍将使用“EllipsisButton” " 在系统的 Generic.xaml 中定义的样式和您的自定义样式将不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 2018-10-17
      • 2017-08-22
      • 1970-01-01
      相关资源
      最近更新 更多