我在查看这个问题时注意到,在Application.Resources中放置隐式TextBlock样式将该样式应用于所有TextBlocks,甚至包括其他控件(如Buttons、ComboBoxes等)中的样式。
<Application.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</Application.Resources>将隐式样式放置在Window.Resources 不交叉控制模板边界。中,这样Buttons和ComboBoxes之类的东西就可以维护其默认的黑色文本。
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</Window.Resources>此外,在Application.Resources中添加默认样式使其不能用另一个隐式样式覆盖该样式。
<!-- Doesn't work if implicit style with same property is in Application.Resources -->
<ComboBox.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red" />
</Style>
</ComboBox.Resources>我的问题是:
Application.Resources和Windows.Resources还有其他区别吗?Application.Resources应用于整个应用程序,而Window.Resources只应用于窗口,但我想知道为什么Application中的样式与Window中的样式不同发布于 2012-02-06 20:41:14
这实际上是添加到WPF中的唯一特殊处理,它是通过设计完成的。在FrameworkElement中可以在FindImplicitStyleResource方法中找到实现它的代码,该方法有效地执行:
internal static object FindImplicitStyleResource(FrameworkElement fe, object resourceKey, out object source)
{
// ...
DependencyObject boundaryElement = null;
if (!(fe is Control))
boundaryElement = fe.TemplatedParent;
// ...
}因此,经验法则是,隐式样式总是应用于控件(即从Control派生)。假设可以找到隐式样式。
对于ControlTemplate中使用的不从Control派生的元素(如TextBlock ),隐式样式查找将不会跨越它的模板父元素。在上面的例子中,这将是ComboBox。
我相信这样做是为了使TextBlock的非应用隐式样式不会无意中应用于控制模板中使用的TextBlock元素,开发人员可能知道也可能不知道。隐式样式只应用于开发人员在自己的XAML中实际创建的TextBlocks。
应用程序隐式样式仍然允许全局样式,例如增加字体大小。但可能造成的混乱比它的价值更多。
没有很好的答案来说明何时使用其中一种与另一种,因为它们各有其功能。显然,如果不想影响应用程序中的每个TextBlock,就不应该将样式放在应用程序资源中。
但请记住,这会影响任何非Control元素,如Shape元素。
发布于 2012-01-27 16:03:52
很简单很简单
如果希望在整个应用程序之间共享资源,可以使用Application.Resources
如果希望在整个窗口之间共享资源,可以使用Window.Resources
如果希望在单个控件之间共享资源,可以使用(任何控件).Resources
假设您有多个窗口,但您只想在一个窗口中使用默认样式,而不是另一个窗口,那么您将使用Windoe.Resources。
发布于 2012-02-04 06:03:31
瑞秋,我不认为“风格”有什么特别之处。此外,不存在“跨越模板边界”的问题。其原因是不同的,它去不同的“树”在一个WPF应用程序。通过你的问题,我发现你描绘的是一个具有以下等级的世界:
没有这样的等级制度。WPF应用程序中有不同的树,其中最著名的是逻辑树和视觉树,但是有更多的树(路由事件树和资源查找树,语义略有不同)。
假设以下XAML:
<Window x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="btn" Click="click">Click Me</Button>
</Grid>
</Window>对于这个XAML,逻辑树如下所示:
按钮中的textblock不是逻辑树的一部分(不过它是VisualTree的一部分)。
通过LogicalTree查找资源,有一个不同之处。在到达顶层对象后,查找资源算法将按此顺序查看应用程序资源字典,然后查看主题资源字典,然后查看系统资源字典。
见下列条款:
最后,为了证明我的观点,将以下资源添加到应用程序XAML中:
<Application x:Class="SO.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
StartupUri="MainWindow.xaml">
<Application.Resources>
<clr:String x:Key="MyResource">Hello Application Resource</clr:String>
</Application.Resources>
</Application>以及下面的代码:
private void click(object sender, RoutedEventArgs e)
{
// Logical Children of btn
Debug.WriteLine("Children of btn:");
foreach( var x in LogicalTreeHelper.GetChildren(btn) ) {
Debug.WriteLine("{0} : {1}", x, x.GetType());
}
// Walk the visual tree
Debug.WriteLine("The Visual Tree:");
WalkVisual(0, this);
// Find the textblock within the button
DependencyObject p = btn;
while (p.GetType() != typeof(TextBlock))
p = VisualTreeHelper.GetChild(p, 0);
TextBlock tb = p as TextBlock;
// Now climp the textblock through the logical tree
while (p != null)
{
Debug.WriteLine("{0}", p.GetType());
p = LogicalTreeHelper.GetParent(p);
}
// Find a resource for the textbox
string s = tb.FindResource("MyResource") as string;
Debug.WriteLine("MyResource Content: {0}", s);
}
private void WalkVisual(int indent, DependencyObject p)
{
string fmt = string.Format("{{0,{0}}}{{1}}", indent * 4);
Debug.WriteLine(fmt, "", p.GetType());
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(p); ++i)
{
WalkVisual(indent+1,VisualTreeHelper.GetChild(p, i));
}
}所以..。一旦你理解了第一个问题(‘为什么是那个’),其他的问题就会分崩离析。应用程序资源和窗口资源的不同之处在于,应用程序资源可以由应用程序中的任何DependencyObject创建,包括在其他程序集中定义的资源。当这是你想要的时候,你就会使用它:-)
u。
https://stackoverflow.com/questions/9035878
复制相似问题