Стили на уровне сборки / корневого уровня в библиотеке классов WPF

У меня есть сборка библиотеки классов 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 окна) - с оговоркой, что это НЕ заявление?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
49
0
17 019
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

если вы загрузите его в Window.Resource, словарь будет доступен только для дочерних элементов этого окна. Он должен быть доступен для окна и его дочерних элементов.

Попробуйте загрузить его в файл app.xaml. Это должно сделать его ресурсом уровня приложения, а не ресурсом уровня окна.

Извините, я полагаю, что изначально я недостаточно прояснил это (я просто изменил описание, чтобы исправить) - у меня нет app.xaml, так как это библиотека классов.

WarpedBoard 01.01.2009 01:14

«Извините, я полагаю, что изначально я недостаточно ясно дал понять». Это stackoverflow, @WarpedBoard. Конечно, вы не ожидаете, что люди действительно прочтут этот вопрос. ;)

mackenir 22.03.2010 19:21

Это похоже на работу по тематике.

  1. Добавьте в проект /themes/generic.xaml ResourceDictionary.
  2. Добавьте в AssemblyInfo.cs следующее: [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
  3. ?
  4. Выгода!

Любые ресурсы, которые вы добавляете в общий, будут использоваться всеми элементами управления. Также вы можете создавать темы для конкретных профилей (Luna, Aero и т. д.), Включив файл ResourceDictionary с правильным названием темы в каталог themes.

Вот ссылка на дополнительную информацию: Создавайте и применяйте собственные темы

Я полагаю, что stackoverflow.com/questions/404019/… - это ответ OP на ваш ответ.

Pat 10.03.2011 02:04

как он знает, что искать /themes/generic.xaml? Это стандарт?

DLeh 18.06.2014 16:41

@DLeh Да /themes/generic.xml - это стандарт. См. msdn.microsoft.com/en-us/library/…

Cameron MacFarland 19.06.2014 12:05

просто поправка (меня поймало) /themes/generic.xaml (обратите внимание на а)

user230910 25.11.2015 14:21

Если у вас нет 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 };

Оно работало завораживающе.

Итак, потратив много времени, я наконец понял это. Вот как:

  1. В библиотеке элементов управления WPF добавьте новую папку с именем themes.
  2. Внутри папки themes добавьте словарь ресурсов с именем generic.xaml.
  3. Внутри generic.xaml добавьте свой ресурс, используя следующий синтаксис:

    <SolidColorBrush x:Key = "{ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}" Color = "Blue" />
    
  4. В вашем элементе управления используйте следующий синтаксис для доступа к этому ресурсу:

    Background = "{StaticResource {ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}}"
    

На заметку:

  1. Шаги 1 и 2 обычно автоматически выполняются Visual Studio при создании новой библиотеки элементов управления WPF.
  2. Я не совсем понимаю назначение первого параметра ComponentResourceKey, но он необходим. Используйте имя элемента управления, который будет использовать этот ресурс.
  3. В моем случае дизайнер Visual Studio не смог найти ресурс. Я не уверен, что это может быть проблема с кешем. Однако во время выполнения он работает аккуратно.
  4. Вы можете прочитать больше об этом синтаксисе в эта статья MSDN.

Надеюсь, это облегчит жизнь некоторым.

Вот простое решение для совместное использование ресурсов «в масштабе модуля» через Библиотека классов .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 ...

Другие вопросы по теме