【问题标题】:WPF Some styles not applied on DataTemplate controlsWPF 某些样式未应用于 DataTemplate 控件
【发布时间】:2011-01-29 09:32:43
【问题描述】:

我正在尝试学习一些关于 WPF 的知识,我对它的灵活性感到非常惊讶。

但是,我遇到了Styles 和DataTemplates 的问题,这有点令人困惑。 我在下面的测试页面中定义了一些样式等,发现<Page.Resources> 中为Border 和TextBlock 定义的Styles 不适用于DataTemplate,但Style 用于@ 987654329@ 的定义方式完全相同。

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

我怀疑它与默认样式等有关,但更令人费解的是为什么有些Styles 被应用而有些则没有。我在任何地方都找不到上述的简单解释,因此想问是否有人愿意用蹩脚的术语解释这种行为,并可能链接到技术描述,即 MSDN 左右。

提前感谢您的支持!

【问题讨论】:

    标签: wpf xaml styles datatemplate


    【解决方案1】:

    我也对此进行了调查,我个人认为这是一个错误。我注意到,如果您这样命名样式,则样式已设置:

    <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 工作的合乎逻辑的方式......

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        这个link对此有更详细的解释,或者你可以查看Connentbug report。

        【讨论】:

        • 感谢您的链接!它解释了发生了什么,但仍然可以链接到官方文档,因为我知道在哪里可以找到这些东西。
        • 在 Microsoft 的 Connect 站点上添加了错误报告的链接,不确定是否有任何官方文档描述了这种行为。
        • 两个链接现在都失效了。找到wayback link for the first one。如果您愿意,请将其添加到您的答案中。
        【解决方案4】:

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

        【讨论】:

        • 你是我的英雄,布莱恩!非常感谢分享。
        猜你喜欢
        • 2018-05-05
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        • 2021-09-09
        • 2011-06-08
        • 2016-09-18
        • 2014-09-21
        • 1970-01-01
        相关资源
        最近更新 更多