WPF:某些样式未应用于DataTemplate控件

34

我正在尝试学习关于WPF的知识,我很惊讶于它的灵活性。

然而,我在Styles和DataTemplates上遇到了问题,这有点令人困惑。 我定义了下面的测试页面来尝试使用样式等,并发现在DataTemplate中没有应用<Page.Resources>中为BorderTextBlock定义的Styles,但是完全相同方式定义的ProgressBarStyle被应用了。

源代码(我只使用Kaxaml和XamlPadX来查看结果)

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <Page.Resources>

    <Style TargetType="{x:Type Border}">
      <Setter Property="Background" Value="SkyBlue"/>
      <Setter Property="BorderBrush" Value="Black"/>
      <Setter Property="BorderThickness" Value="2"/>
      <Setter Property="CornerRadius" Value="5"/>
    </Style>

    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="FontWeight" Value="Bold"/>
    </Style>

    <Style TargetType="{x:Type ProgressBar}">
      <Setter Property="Height" Value="10"/>
      <Setter Property="Width" Value="100"/>
      <Setter Property="Foreground" Value="Red"/>
    </Style>

    <XmlDataProvider x:Key="TestData" XPath="/TestData">
      <x:XData>
        <TestData xmlns="">
          <TestElement>
            <Name>Item 1</Name>
            <Value>25</Value>
          </TestElement>
          <TestElement>
            <Name>Item 2</Name>
            <Value>50</Value>
          </TestElement>
        </TestData>
      </x:XData>
    </XmlDataProvider>

    <HierarchicalDataTemplate DataType="TestElement">
      <Border Height="45" Width="120" Margin="5,5">
        <StackPanel Orientation="Vertical" Margin="5,5" VerticalAlignment="Center" HorizontalAlignment="Center">
          <TextBlock HorizontalAlignment="Center" Text="{Binding XPath=Name}"/>
          <ProgressBar Value="{Binding XPath=Value}"/>
        </StackPanel>
      </Border>
    </HierarchicalDataTemplate>

  </Page.Resources>

  <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
    <StackPanel Orientation="Vertical" VerticalAlignment="Center">
      <Border Height="45" Width="120" Margin="5,5">
        <StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
          <TextBlock HorizontalAlignment="Center" Text="Item 1"/>
          <ProgressBar Value="25"/>
        </StackPanel>
      </Border>
      <Border Height="45" Width="120" Margin="5,5">
        <StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
          <TextBlock HorizontalAlignment="Center" Text="Item 2"/>
          <ProgressBar Value="50"/>
        </StackPanel>
      </Border>
    </StackPanel>
    <ListBox Margin="10,10"  Width="140" ItemsSource="{Binding Source={StaticResource TestData}, XPath=TestElement}"/>
  </StackPanel>
</Page>
我怀疑这与默认样式等有关,但更令人困惑的是为什么某些“样式”被应用而某些未被应用。我无法在任何地方找到简单的解释,因此希望有人能够用通俗易懂的方式解释这种行为,并提供可能涉及MSDN或其他技术描述的链接。
非常感谢您的支持!
4个回答

39

我找到了一个简单的解决方法。对于那些不能在数据模板封装边界之外进行搜索(即未被隐式样式化的元素),您可以在该元素类型的数据模板中声明一个空样式,并使用该样式的BasedOn属性来查找正确的数据模板外部的隐式样式应用。

在下面的示例中,TextBox能够在数据模板封装边界之外进行搜索(因为它从Control继承?),但TextBlock不能进行搜索,因此我为它声明了空样式,以便它可以在数据模板之外进行搜索。

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <DataTemplate.Resources>
            <Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
        </DataTemplate.Resources>
        <DockPanel>
            <TextBlock Text="{Binding Name}"  />
            <TextBox Text="{Binding Value}" />
        </DockPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>

你是我的英雄,布莱恩!非常感谢你的分享。 - Sergey Volodko

34

这实际上是有意设计的。不从 Control 派生的元素,除非它们在应用程序资源中,否则不会获取隐式样式。

您可以查看此链接以了解更多详细信息,或查看 Connent 错误报告


感谢提供链接!它解释了正在发生的事情,但是提供官方文档的链接会更好,这样我就知道在哪里查找这些信息。 - Martin
在微软的Connect网站上添加了错误报告链接,不确定是否有任何官方文件描述了这种行为。 - CodeNaked
9
现在这两个链接都无法访问。找到了第一个链接的 Wayback 镜像地址:https://web.archive.org/web/20170201072114/http://www.11011.net/archives/000692.html。如果您愿意,可以将其添加到您的回答中。 - itsho

4

我也研究过这个问题,个人认为这是一个bug。我注意到,如果你按以下方式命名样式,样式会被设置:

<Style x:Key="BorderStyle" TargetType="{x:Type Border}">
etc...

并明确设置您的DataTemplate以使用这些样式:

<HierarchicalDataTemplate DataTemplate="TestElement">
  <Border Height="45" Width="120" Margin="5,5", Style="{StaticResource BorderStyle}">

我认为对于DataTemplates(以及可能是ControlTemplates),它们默认情况下没有样式,除非您明确设置它们。

对我来说,这不应该发生- 这不是WPF工作的逻辑方式...


0
这是因为ListBox是数据模板项的逻辑父级,现在记住,所有可继承的属性,如字体、前景色等,都是从逻辑父级派生的,而ListBox已经在其自己的默认样式中覆盖了它,这就是为什么它不起作用的原因。然而,在这种情况下,您可以像Dave先生建议的那样使用命名样式,但我认为如果它不起作用,那么这是List Box等情况下已知的问题,您可以参考我的问题here, i had similar problem in listbox,并且我的问题的答案更详细。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接