在Application.Resources vs Window.Resources隐式样式?
我正在看这个问题,并注意到在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
样式
这实际上是添加到WPF的唯一特殊处理,并且是通过devise完成的。 实现它的代码可以在FrameworkElement
的FindImplicitStyleResource
方法中FindImplicitStyleResource
,它有效地:
internal static object FindImplicitStyleResource(FrameworkElement fe, object resourceKey, out object source) { // ... DependencyObject boundaryElement = null; if (!(fe is Control)) boundaryElement = fe.TemplatedParent; // ... }
所以经验法则是隐式样式总是应用于控件(即派生自Control
)。 假设可以find隐含的风格。
对于ControlTemplate
中不能派生自Control
元素(例如TextBlock
,隐式Style查找不会跨越模板化的父元素。 在你的情况上面,这将是ComboBox
。
我相信这样做是为了使TextBlock的非应用程序隐式样式不会无意中应用于控件模板中使用的TextBlock
元素,而开发人员可能已经知道这些元素。 隐式样式仅适用于由开发人员在其自己的XAML中实际创build的TextBlocks。
应用程序隐式样式仍然允许全局样式,例如增加字体大小。 但可能会造成更多的混乱,而不是价值。
没有什么好的答案说什么时候使用一个和另一个,因为他们每个人都有自己的function。 显然,如果你不想影响你的应用程序中的每个TextBlock
,你不应该把样式放在应用程序资源中。
但请记住,这会影响非Control
元素,例如Shape
元素。
很简单,很简单
如果您希望在整个应用程序之间共享资源,您可以使用Application.Resources
如果你想在整个窗口之间共享资源,你可以使用Window.Resources
如果您希望资源在单个控件之间共享,您将使用(不pipe控制).Resources
比方说,你有多个窗口,但你只想在一个默认的风格,但不是其他,那么你会使用Windoe.Resources
Rachel,我不觉得“Styles”有什么特别之处。 而且,不存在“跨越模板边界”的问题。 其原因是不同的,它在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,逻辑树将如下所示:
– Window => Grid => Button => String
button内的文本块不是逻辑树的一部分(尽pipe它是VisualTree的一部分)。
寻找资源是由LogicalTree,有一个区别。 在到达顶层对象后,查找资源algorithm将查看应用程序资源字典,然后在主题资源diectionary中,然后按照此顺序在System资源字典中。
请参阅以下文章:
- 关于树: http : //msdn.microsoft.com/en-us/library/ms753391.aspx
- 关于查找资源: http : //msdn.microsoft.com/en-us/library/ms750613.aspx#staticdynamic ,然后查找“dynamic资源查找行为”
Finnaly,为了certificate我的观点,将以下资源添加到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提供,包括在其他程序集中定义的应用程序资源。 你会使用它,当这是你想要实现的:-)
ü。
区别在于风格的范围:
- 当放置在Application.Resources中时,样式将应用于应用程序中的所有控件
- 当放置在Windows.Resources中时,样式将应用于窗口中的所有控件
那里的区别是相当微妙的,但是它意味着我们所谈论的任何控制(包括在另一个控件的模板中的控件)都将从application.Resources中获得样式。 但是只有窗口的子控件才会从window.Resources中获取样式。 Antoher控件模板中的控件不会在Window.Resources中定义样式,因为它不是直接在窗口中,而是在Application.Resources中定义的样式,因为它在应用程序中。
至于你的第二点,它与依赖属性的优先顺序,我认为: