WPF Некоторые стили не применяются к элементам управления DataTemplate - PullRequest
29 голосов
/ 19 марта 2010

Я пытаюсь что-то узнать о WPF, и я очень удивлен его гибкостью.

Однако я столкнулся с проблемой Style s и DataTemplate s, что немного сбивает с толку. Я определил ниже тестовую страницу, чтобы немного поиграть со стилями и т. Д. И обнаружил, что Style s, определенные в <Page.Resources> для Border и TextBlock, не применяются в DataTemplate, но 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 применяются, а некоторые нет. Я нигде не могу найти легкого объяснения вышеизложенного и поэтому хотел бы спросить, будет ли кто-то достаточно любезен, чтобы объяснить это поведение в терминах ламенов с возможными ссылками на техническое описание, т.е. на MSDN или около того.

Заранее спасибо за поддержку!

Ответы [ 4 ]

32 голосов
/ 07 июня 2013

Я обнаружил простой обходной путь для этого.Для любых элементов, которые не могут выполнять поиск за пределами границы инкапсуляции шаблона данных (т.е. не имеют неявного стиля), вы можете просто объявить пустой стиль в шаблоне данных для этого типа элемента и использовать атрибут 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>
30 голосов
/ 19 марта 2010

Это на самом деле задумано. Элементы, которые не являются производными от Control, не получат неявные стили, если они не находятся в ресурсах приложения.

Эта ссылка объясняет это более подробно, или вы можете просмотреть отчет об ошибке Connent .

3 голосов
/ 19 марта 2010

Я тоже это изучал и лично считаю, что это ошибка. Я заметил, что стиль установлен, если вы называете свои стили следующим образом:

<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 голосов
/ 19 марта 2010

Это потому, что ListBox является логическим родителем ваших элементов таблицы данных, теперь помните, что все свойства, которые являются «наследуемыми», такие как font, forecolor и т. Д., Являются производными от логического родителя, и ListBox уже переопределяет его в своем собственном стиле по умолчанию, то есть почему это не сработает. Однако в этом случае вы можете использовать именованные стили, как предложил г-н Дейв, но я думаю, что если это не сработает, то это известная проблема в случае со списком и т. Д., Вы можете обратиться к моему вопросу здесь, я была похожая проблема в списке , и ответы на мой вопрос более подробно.

...