Рейчел, я не думаю, что ничего особенного в «Стили». Более того, не существует вопроса о «пересечении границ шаблонов». Причина этого различна, и она переходит к различным «деревьям» в приложении WPF. По вашему вопросу я Recon вы изображая мир со следующей иерархией:
- Применение => Window => Control => Элементы внутри элемента управления
Там нет такой иерархии. В приложении 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 => Сетка => Кнопка => Строка
Объект TextBlock внутри кнопки является не является частью логического дерева (хотя это часть VisualTree).
Искание ресурсов осуществляется LogicalTree с разницей. После того, как он достигнет верхнего объекта, алгоритм поиска ресурса будет смотреть на ресурсный словарь , а затем на 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.
Хороший вопрос и понимание о том, как неявные стили пересечения границы App.xaml ControlTemplate. Из-за этого я импортирую/объединяя определенные ресурсные словари в * каждый * из моих окон приложения (я действительно просто импортирую только один мастер-файл). Вы нашли лучший способ решить эту проблему, чем то, как я это делаю? (Было бы лучше иметь возможность просто импортировать его один раз - как мы это делаем с импортированными ресурсами App.xaml.) –
Эта проблема с границей ControlTemplate особенно затруднительна для случаев, таких как (App.xaml-level) неявный TextBlock, где TextBlock автоматически генерируется как дочерний элемент ContentPresenter элемента управления. Используя трюк на уровне окна, который Рейчел упоминает, решил эту проблему для меня. –
@Jason Обычно мои приложения WPF имеют только одно окно, при этом содержимое изменяется по мере необходимости. Я не думаю, что я когда-либо делал то, что было более двух окон (вход и приложение). Тем не менее, вы, вероятно, могли бы использовать MEF для импорта/экспорта ресурсных словарей, как описано [здесь] (http://stackoverflow.com/q/842571/302677) – Rachel