Рэйчел, я не думаю, что есть что-то особенное для "Стилей".Более того, нет проблемы «пересечения границ шаблона».Причина этого в другом, и это относится к разным «деревьям» в приложении 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
Текстовый блок внутри кнопки не является частью логического дерева (хотя является частью VisualTree).
Поиск ресурсов идетпо логическому дереву, с одним отличием.После того, как он достигнет верхнего объекта, алгоритм поиска ресурсов будет искать словарь ресурсов Application , затем каталог ресурсов Theme , а затем System словарь ресурсов в следующем порядке.
Смотрите следующие статьи:
Finnaly, чтобы доказать мою точку зрения, добавьте в приложение 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.