У меня есть сборка библиотеки классов C# (2008 / .NET 3.5), которая поддерживает WPF (на основе эта статья) .
Я создал несколько окон и теперь пытаюсь создать для них общий набор стилей. Однако, поскольку это библиотека классов (вместо приложения WPF), у меня нет app.xaml (и содержащегося в нем Application и соответствующего Application.Resources), в котором можно было бы хранить эти стили для глобального доступа.
Так: Как я могу создать набор определений стилей верхнего уровня, который будет виден всем файлам xaml в сборке, учитывая, что у меня нет app.xaml (см. выше)? И / или возможно ли Добавлять рабочего app.xaml в библиотеку классов?
К вашему сведению, я попытался создать ResourceDictionary в файле ResourceDictionary.xaml и включить его в каждое окно в блоке Window.Resources. Оказалось, что это решило проблему стиля кнопок и т. д., Но не для закрывающего окна. Я могу поместить Style = "{StaticResource MyWindowStyle}" в блок открытия окна, и он компилируется и отображается в окне VS Design нормально, но во время фактического выполнения я получаю исключение синтаксического анализа (MyWindowStyle не может быть найден; я предполагаю, что Visual Studio видит словарь, включенный после строка, о которой идет речь, но CRL выполняет действия более последовательно и, следовательно, еще не загрузил ResourceDictionary).
Спасибо за идеи, но все равно нет ... очевидно, библиотека классов НЕ поддерживает использование generic.xaml неявно. Я добавил generic.xaml в свой проект библиотеки классов и установил для его действия Build Action значение «Resource». Это содержит:
<ResourceDictionary
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType = "{x:Type Window}" x:Key = "MyWindow">
<Setter Property = "Background" Value = "Black"/>
</Style>
</ResourceDictionary>
Окно xaml, в котором я хочу использовать тему, выглядит так:
<Window x:Class = "MyAssembly.ConfigureGenericButtons"
x:ClassModifier = "internal"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Style = "{StaticResource MyWindow}"
Title = "ConfigureGenericButtons">
...Buttons, etc...
</Window>
Хотя в окне VS Design окно не отображается в стиле MyWindow (т.е. на черном фоне), оно компилируется и запускается нормально. Однако, когда приложение, содержащее эту библиотеку классов, выполняет вызов, вызывающий отображение этого окна, я получаю исключение XamlParseException:
Cannot find resource named '{MyWindow}'.
Я также попытался опустить параметр Style, чтобы увидеть, будет ли окно использовать стиль по умолчанию (и я пробовал это как с включенным x: Key в generic.xaml, так и без него). Ошибок нет, но ничего, что определено в generic.xaml, тоже не появлялось.
Я делаю здесь что-то не так, или какие-либо другие идеи о том, как можно разрешить использование общих пользовательских стилей в окне (т.е. не нужно определять стили в каждом xaml окна) - с оговоркой, что это НЕ заявление?





если вы загрузите его в Window.Resource, словарь будет доступен только для дочерних элементов этого окна. Он должен быть доступен для окна и его дочерних элементов.
Попробуйте загрузить его в файл app.xaml. Это должно сделать его ресурсом уровня приложения, а не ресурсом уровня окна.
«Извините, я полагаю, что изначально я недостаточно ясно дал понять». Это stackoverflow, @WarpedBoard. Конечно, вы не ожидаете, что люди действительно прочтут этот вопрос. ;)
Это похоже на работу по тематике.
/themes/generic.xaml ResourceDictionary.[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]Любые ресурсы, которые вы добавляете в общий, будут использоваться всеми элементами управления. Также вы можете создавать темы для конкретных профилей (Luna, Aero и т. д.), Включив файл ResourceDictionary с правильным названием темы в каталог themes.
Вот ссылка на дополнительную информацию: Создавайте и применяйте собственные темы
Я полагаю, что stackoverflow.com/questions/404019/… - это ответ OP на ваш ответ.
как он знает, что искать /themes/generic.xaml? Это стандарт?
@DLeh Да /themes/generic.xml - это стандарт. См. msdn.microsoft.com/en-us/library/…
просто поправка (меня поймало) /themes/generic.xaml (обратите внимание на а)
Если у вас нет app.xaml, вы все равно можете загрузить его в ресурсы уровня приложения, но вам нужно написать код (не xaml), чтобы сделать это, аналогично этому ...
void LoadIt()
{
ResourceDictionary MyResourceDictionary = new ResourceDictionary();
MyResourceDictionary.Source = new Uri("MyResources.xaml", UriKind.Relative);
App.Current.Resources.MergedDictionaries.Add( MyResourceDictionary )
}
посмотрите этот сайт для примера:
http://ascealedguard.com/2007/08/one-of-nice-features-about-wpf-is-how.html
Попробуйте добавить
Style = {DynamicResource MyStyle}
В этом случае нельзя использовать StaticResource.
У доктора WPF (или человека, ранее известного как доктор WPF) отличный Почта по этому вопросу.
Вот отрывок из сообщения, в котором они создают объект Application и добавляют ресурсы:
if (Application.Current == null)
{
// create the Application object
new Application();
// merge in your application resources
Application.Current.Resources.MergedDictionaries.Add(
Application.LoadComponent(
new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml",
UriKind.Relative)) as ResourceDictionary);
}
Поскольку моя сборка размещена через взаимодействие, мне пришлось добавить настройку ShutdownMode следующим образом и выключение по завершении:
new Application() { ShutdownMode = ShutdownMode.OnExplicitShutdown };
Оно работало завораживающе.
Итак, потратив много времени, я наконец понял это. Вот как:
themes.themes добавьте словарь ресурсов с именем generic.xaml.Внутри generic.xaml добавьте свой ресурс, используя следующий синтаксис:
<SolidColorBrush x:Key = "{ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}" Color = "Blue" />
В вашем элементе управления используйте следующий синтаксис для доступа к этому ресурсу:
Background = "{StaticResource {ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}}"
На заметку:
ComponentResourceKey, но он необходим. Используйте имя элемента управления, который будет использовать этот ресурс.Надеюсь, это облегчит жизнь некоторым.
Вот простое решение для совместное использование ресурсов «в масштабе модуля» через Библиотека классов .NET. Важно отметить, что он, похоже, надежно сохраняет возможности и поведение отображения Конструктор XAML в Visual Studio.
Начните с добавления нового класса C#, производного от ResourceDictionary, как показано ниже. Экземпляр этого класса заменит ResourceDictionary по умолчанию на каждом System.Windows.Control (или другом компоненте, несущем ResourceDictionary) в библиотеке классов, который должен видеть общие ресурсы:
ComponentResources.cs:
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
namespace MyNamespace
{
[UsableDuringInitialization(true), Ambient, DefaultMember("Item")]
public class ComponentResources : ResourceDictionary
{
static ResourceDictionary _inst;
public ComponentResources()
{
if (_inst == null)
{
var uri = new Uri("/my-class-lib;component/resources.xaml", UriKind.Relative);
_inst = (ResourceDictionary)Application.LoadComponent(uri);
}
base.MergedDictionaries.Add(_inst);
}
};
}
Обязательно замените MyNamespace и my-class-lib в предыдущем фрагменте кода на (соответственно) пространство имен и имя файла сборки (без расширения '.dll') из вашего собственного проекта:
Добавьте новый файл ResourceDictionaryXAML в свой проект библиотеки классов. В отличие от сборок «Приложение», в пользовательском интерфейсе Visual Studio для этого нет опции, поэтому вам придется делать это вручную. Он будет содержать ресурсы, которые вы хотите использовать во всей библиотеке классов:
$ (ProjectDirectory) \ Resources.xaml:
<ResourceDictionary xmlns = "http://schemas.microsoft.com/netfx/2009/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:MyNamespace">
<!-- define the resources to be shared across the whole class library here -->
<!-- example for demonstration -->
<Style TargetType = "Rectangle">
<Setter Property = "Fill" Value = "Red" />
</Style>
<ResourceDictionary>
Установите Построить действие на "Страница" и убедитесь, что информация о свойствах файла выглядит следующим образом:
Наконец, перейдите к файлам XAML в проекте, которые должны ссылаться на общие ресурсы, и замените ResouceDictionary по умолчанию (обычно в свойстве Resources корневого элемента XAML) экземпляром ComponentResources. Он будет содержать частные ресурсы каждого компонента, и, как вы можете видеть в приведенном выше коде, конструктор присоединяет общий синглтон для всего модуля ResourceDictionary как «объединенный словарь». Сделайте это для каждого элемента управления, который должен видеть общие ресурсы, даже для тех, у которых нет собственных частных ресурсов. Конечно, вы также можете пропустить этот шаг, чтобы при необходимости исключить определенные элементы управления из общего доступа. Например:
<UserControl x:Class = "MyNamespace.UserControl1"
xmlns = "http://schemas.microsoft.com/netfx/2009/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:MyNamespace">
<UserControl.Resources>
<local:ComponentResources>
<!-- Keep any existing non-shared resources here from before -->
<!-- Can be empty if this control has no private resources -->
</local:ComponentResources>
</UserControl.Resources>
<!-- to demonstrate that the Style in the above example is effective... -->
<Grid>
<Rectangle Width = "10" Height = "10" />
</Grid>
</UserControl>
Как рекламируется, отлично работает, в том числе в Конструктор XAML ...
Извините, я полагаю, что изначально я недостаточно прояснил это (я просто изменил описание, чтобы исправить) - у меня нет app.xaml, так как это библиотека классов.