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

时间:2010-03-19 09:59:03

标签: wpf xaml styles datatemplate

我正在尝试学习WPF,我对其灵活性感到非常惊讶。

但是,我遇到了StyleDataTemplate s的问题,这有点令人困惑。 我在下面的测试页面中定义了一些样式等,并发现Style <Page.Resources>Border中定义的TextBlock未应用于{DataTemplate 1}},但应用Style ProgressBar以完全相同的方式定义。

源代码(我只使用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>

我怀疑它与默认样式等有关,但更令人费解的是为什么应用了一些Style而有些则没有。我无法在任何地方找到一个简单的解释,因此想问一下是否有人能够用lamens的术语解释这种行为,并附有可能的技术描述链接,即MSDN左右。

先谢谢你的支持!

4 个答案:

答案 0 :(得分:32)

我发现了一个简单的解决方法。对于无法在数据模板封装边界外搜索的任何元素(即未进行隐式设置),您只需在数据模板中为该元素类型声明一个空样式,并使用该属性的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>

答案 1 :(得分:30)

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

link更详细地解释了这一点,或者您可以查看Connent bug report

答案 2 :(得分:3)

我也研究了这个,我个人认为这是一个错误。我注意到如果你给你的样式命名就设置了样式:

<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),它们可能默认使用null样式,除非您明确设置它们。

这对我来说并不意味着发生 - 这不是WPF工作的合理方式......

答案 3 :(得分:0)

这是因为ListBox是你的datatemplate项的逻辑父项,现在记住,所有那些“可继承”的属性,如font,forecolor等,都是从逻辑父派生的,而ListBox已经用它自己的默认样式覆盖它,那就是为什么这不起作用。但是在这种情况下,您可以像Dave先生所建议的那样使用命名样式,但我认为如果它不起作用那么这是列表框等的已知问题,您可以参考我的问题here, i had similar problem in listbox,我的问题中的答案更详细。