我需要帮助,因为我不明白为什么来自datatemplate的控件不会继承窗口资源中定义的样式。 可能有解决方法吗?
如果有人能给我一个解决方案,我会非常感激,因为我花了很多时间找到一些东西。
特此我的例子。例如,horrizontal模板中的Texblock不对齐:
Udapte: 我添加了背景颜色。该样式适用于标签,但不适用于由datatemplate定义的totextblock和textbox。
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:localview="clr-namespace:WpfApplication3"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="{x:Type TextBlock}" TargetType="TextBlock" >
<Setter Property="Background" Value="Cyan"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="FontFamily" Value="Comic Sans MS"/>
</Style>
<Style x:Key="{x:Type Label}" TargetType="Label">
<Setter Property="Background" Value="Red"/>
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style x:Key="{x:Type TextBox}" TargetType="TextBox">
<Setter Property="Background" Value="Cyan"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
</Style>
<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
</Style>
<localview:TemplateSelector x:Key="TemplateSelector">
<localview:TemplateSelector.DataTemplateH>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="Value"/>
<TextBox Text="{Binding Path=SelectedItem.Content ,ElementName=Combo}"/>
</StackPanel>
</DataTemplate>
</localview:TemplateSelector.DataTemplateH>
<localview:TemplateSelector.DataTemplateV>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Content="Value"/>
<StackPanel Orientation="Horizontal">
<Label Content="new line"/>
**<TextBlock Text="{Binding Path=SelectedItem.Content ,ElementName=Combo}" TextAlignment="Right"/>**
</StackPanel>
</StackPanel>
</DataTemplate>
</localview:TemplateSelector.DataTemplateV>
</localview:TemplateSelector>
</Window.Resources>
<StackPanel Orientation="Vertical">
<StackPanel>
<TextBlock Text="Texblock"/>
<TextBox Text="Texblock"/>
<StackPanel Orientation="Horizontal">
<Label Content="Value"/>
<ComboBox Name="Combo">
<ComboBox.Items>
<ComboBoxItem Content="H"/>
<ComboBoxItem Content="V"/>
</ComboBox.Items>
</ComboBox>
</StackPanel>
<ContentControl ContentTemplateSelector="{StaticResource TemplateSelector}"
Content="{Binding Path=SelectedItem.Content ,ElementName=Combo}" />
</StackPanel>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Reflection;
namespace WpfApplication3
{
public class TemplateSelector : DataTemplateSelector
{
public DataTemplate DataTemplateH
{
get;
set;
}
public DataTemplate DataTemplateV
{
get;
set;
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
string s = (string)item;
if (s == "H")
return DataTemplateH;
if (s == "V")
return DataTemplateV;
return base.SelectTemplate(item, container);
}
}
}
答案 0 :(得分:7)
为了阐明为什么 TextBlock
找不到它的隐式样式,WPF中有一个奇怪的规则隐式样式只能通过元素跨模板边界继承继承自Control
类;不从Control
继承的元素不会探测父模板之外的隐式样式。
可以在FrameworkElement
:
// FindImplicitSytle(fe) : Default: unlinkedParent, deferReference
internal static object FindImplicitStyleResource(
FrameworkElement fe,
object resourceKey,
out object source)
{
...
// For non-controls the implicit StyleResource lookup must stop at
// the templated parent. Look at task 25606 for further details.
DependencyObject boundaryElement = null;
if (!(fe is Control))
{
boundaryElement = fe.TemplatedParent;
}
...
}
Carole Snyder在微软explains the reasons for this behavior:
我给出的原因是控件比元素更明显,并且控件的隐式样式应该应用于任何地方,其中元素的隐式样式不太可能是普遍适用。这个论点是合理的。请考虑以下事项:
<StackPanel> <StackPanel.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="16"/> <Setter Property="Foreground" Value="Green"/> </Style> </StackPanel.Resources> <TextBlock HorizontalAlignment="Center" Text="Hello!"/> <Button Content="Click me!" Width="200"/> <TextBlock HorizontalAlignment="Center" Text="Please click the button"/> </StackPanel>
Button通过最终创建TextBlock并将字符串添加到TextBlock来显示字符串。如果Button中的TextBlock使用了应用程序定义的隐式样式,则XAML将以这种方式呈现:
这可能不是你想要的行为。另一方面,假设您正在创建一个很酷的UI,并且您希望所有的RepeatButton都具有特定的外观。如果你定义一次RepeatButton的外观,所有RepeatButtons将使用该外观,即使RepeatButton在ControlTemplate中。
答案 1 :(得分:3)
我刚刚尝试了一些简单的演示,是的答案是你不能将模板外部的默认样式应用到一些TextBlock 里面 模板(包括DataTemplate)和ControlTemplate)。这不会发生在其他控件上,例如Label,TextBox(虽然你也说过Style不适用于TextBox,但是我试过它,实际上并非如此)。
要解决此问题,最好的方法是为TextBlock明确设置样式,如下所示:
<TextBlock Text="{Binding Path=SelectedItem.Content ,ElementName=Combo}"
TextAlignment="Right" Style="{StaticResource {x:Type TextBlock}}"/>
请注意,正如我所说,只有TextBlocks 模板(DataTemplate和ControlTemplate)才需要。
代码看起来相当荒谬,但它实际上是有效的,没有这样做,因为你认为它不起作用。