WPF Некоторые стили, не применяемые к элементам управления DataTemplate
Я пытаюсь узнать что-то о WPF, и я очень поражен его гибкостью.
Однако я столкнулся с проблемой с Style
и DataTemplate
s, что немного запутывает.
Я определил ниже тестовую страницу, чтобы немного поиграть со стилями и обнаружил, что Style
, определенный в <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 или так.
Заранее благодарю вас за поддержку!
Ответы
Ответ 1
Это на самом деле по дизайну. Элементы, которые не выводятся из Control, не будут получать неявные стили, если они не находятся в ресурсах приложения.
Эта ссылка объясняет это более подробно или вы можете просмотреть Connent отчет об ошибках.
Ответ 2
Я обнаружил простую обходную процедуру для этого. Для любых элементов, которые не могут выполнять поиск за пределами границы инкапсуляции шаблона данных (т.е. Неявно оформлены), вы можете просто объявить пустой стиль в шаблоне данных для этого типа элемента и использовать атрибут 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>
Ответ 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) возможно, что они по умолчанию имеют нулевой стиль, если вы явно не установили их.
То, что мне не предназначено, - это не логичный способ работы WPF...
Ответ 4
Это связано с тем, что ListBox является логическим родителем ваших элементов datatemplate, теперь помните, что все свойства, которые являются "наследуемыми", такие как font, forecolor и т.д., получены из логического родителя, а ListBox уже переопределяет его в собственном стиле по умолчанию, почему это не сработает. Однако в этом случае вы можете использовать именованные стили, как предложил г-н Дейв, но я думаю, что если это не сработает, то это известная проблема в случае списка Box и т.д., Вы можете ссылаться на мой вопрос здесь, у меня была аналогичная проблема в списке, и ответы в моем вопросе более подробно.