【问题标题】:Understanding WPF Control Styles and Templates了解 WPF 控件样式和模板
【发布时间】:2012-10-11 01:58:07
【问题描述】:

我对 .NET/C#/WPF/XAML 比较陌生。我注意到有时控件似乎“缺少”影响样式的最简单属性。因此,必须使用类Style 来修改控件的外观。这没关系,但我发现自己在 Google/StackOverflow 上寻找要修改的特定属性的名称。

我正在为 ALL .NET Framework WPF 控件寻找规范且完整的默认控件样式和模板来源。

在你回答得太快之前,请继续阅读以了解我的困惑。

在此 Microsoft 文档页面 DataGrid Styles and Templates 上,我看到了 DataGridCell 的模板:

<!--Style and template for the DataGridCell.-->
<Style TargetType="{x:Type DataGridCell}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridCell}">
        <Border x:Name="border"
                BorderBrush="Transparent"
                BorderThickness="1"
                Background="Transparent"
                SnapsToDevicePixels="True">
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="FocusStates">
              <VisualState x:Name="Unfocused" />
              <VisualState x:Name="Focused" />
            </VisualStateGroup>
            <VisualStateGroup x:Name="CurrentStates">
              <VisualState x:Name="Regular" />
              <VisualState x:Name="Current">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="border"
                                                Storyboard.TargetProperty="(Border.BorderBrush).
                      (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DatagridCurrentCellBorderColor}" />
                  </ColorAnimationUsingKeyFrames
                                                >
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

This page from MSDN forums,显示如下Style/Triggers/Setters。

<SolidColorBrush x:Key="{x:Static DataGrid.FocusBorderBrushKey}" Color="#FF000000"/>
 <Style TargetType="{x:Type DataGridCell}">
 <Setter Property="Background" Value="Transparent"/>
 <Setter Property="BorderBrush" Value="Transparent"/>
 <Setter Property="BorderThickness" Value="1"/>
 <Setter Property="Template">
  <Setter.Value>
  <ControlTemplate TargetType="{x:Type DataGridCell}">
   <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
   <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
   </Border>
  </ControlTemplate>
  </Setter.Value>
 </Setter>
 <Style.Triggers>
  <Trigger Property="IsSelected" Value="True">
  <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
  <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
  <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
  </Trigger>
  <Trigger Property="IsKeyboardFocusWithin" Value="True">
  <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/>
  </Trigger>
 </Style.Triggers>
 </Style>

为什么我在第一个模板中看不到属性BackgroundForegroundBorderBrush

我感觉VisualState 的东西是一个参考,但我找不到来源。

【问题讨论】:

    标签: c# wpf xaml templates styles


    【解决方案1】:

    嗯,ContentPresenter 是一个显示您的内容的控件。 VisualState 的东西只是保存控件 DataGridCell 可以遇到的所有 VisualState 的引用。它在包装了 ContentPresenter 的属性边框上放置了一些动画。

    你可以重新定义整个Style,我的意思是放一些其他的控件来重新定义内容,并使用TemplateBinding来获取外部依赖属性。就像我的意思是你甚至可以在 VisualState 的边界上使用TemplateBinding Background

        <Style TargetType="{x:Type DataGridCell}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type DataGridCell}">
            <Border x:Name="border"
                    BorderBrush=BorderBrush}" BorderThickness="{TemplateBinding      BorderThickness}" Background="{TemplateBinding Background}"
                    SnapsToDevicePixels="True">
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="FocusStates">
                  <VisualState x:Name="Unfocused" />
                  <VisualState x:Name="Focused" />
                </VisualStateGroup>
                <VisualStateGroup x:Name="CurrentStates">
                  <VisualState x:Name="Regular" />
                  <VisualState x:Name="Current">
                    <Storyboard>
                      <ColorAnimationUsingKeyFrames Storyboard.TargetName="border"
                                                    Storyboard.TargetProperty="(Border.BorderBrush).
                          (SolidColorBrush.Color)">
                        <EasingColorKeyFrame KeyTime="0"
                                             Value="{StaticResource DatagridCurrentCellBorderColor}" />
                      </ColorAnimationUsingKeyFrames
                                                    >
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
              <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    

    这完全有道理。但是,如果您没有为样式指定它们,则意味着它将回退到已为控件定义的默认颜色和背景等。

    这是每个dependencyProperty 的一个属性,当新值不覆盖它时回退到默认值。

    您可以阅读我的 WPF 教程以获取更多类似这样的概念: http://www.abhisheksur.com/2010/12/wpf-tutorial.html

    【讨论】:

      【解决方案2】:

      您可以在此处下载 WPF 控件Default WPF Themes 的默认样式字典。 如果您必须重新设置控件的样式,了解默认样式的工作原理会非常有帮助。

      【讨论】:

      • 没错。这花了我一些深入的研究来理解。默认 ControlTemplate(参见属性 Control.Template)与其默认样式(或“主题”)之间存在差异。当您使用自定义样式覆盖/修改时,您还可以指定新的 ControlTemplate。一开始有点混乱!
      • 链接已关闭。 this link很有用
      猜你喜欢
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      相关资源
      最近更新 更多