Расширение / переопределение стиля в словаре ресурсов

StackOverflow https://stackoverflow.com/questions/1209128

Вопрос

У меня есть BaseSkin и несколько UserSkins в отдельной dll от моего приложения WPF.

В зависимости от того, кто использует приложение, базовый скин и один из пользовательских скинов будут объединены в словарь ресурсов и загружены для использования приложением.

То, к чему я стремлюсь, - это возможность указать стиль в файле BaseSkin, а затем в конкретном файле UserSkin иметь возможность переопределить его, изменив любые нужные мне свойства.

Я знаю, что могу сделать это, используя атрибут BasedOn, например так:

База:

<Style x:Key="ButtonBg" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Green"/>
</Style>

Пользователь:

<Style x:Key="CustomButtonBg" TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonBg}">
    <Setter Property="Background" Value="Blue"/>
</Style>

Проблема в том, что теперь элементы должны иметь стиль CustomButtonBg, который на самом деле не может быть реализован. Есть ли способ, чтобы оба стиля использовали один и тот же ключ (ButtonBg), и когда они объединяются, приложение сначала ищет стиль с именем ButtonBg в User, а если он не существует, используйте его в базе? / р>

Я думал, что, если бы я мог дать имя сборки в атрибуте BasedOn, чтобы он указывал на файл BaseSkin, я мог бы избежать ошибок именования, когда я даю им тот же ключ, но я не могу найти никакого способа сделать это. Другими вариантами является принудительная реализация каждого стиля, даже если ничего не изменилось, или программная проверка в скинах, но это последние средства.

Это было полезно?

Решение

Вы можете попробовать воспользоваться логикой поиска ресурса. Когда WPF пытается найти ресурс по ключу, он сначала просматривает текущий элемент ResourceDictionary , затем его родительский элемент, затем родительский элемент этого и т. Д.

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

Изменить. У меня есть более точная информация. MSDN в объединенных словарях :

  

Поведение объединенного словаря

     

Ресурсы в объединенном словаре занимают место в области поиска ресурсов, которое находится сразу после области основного словаря ресурсов, в которую они объединяются. Хотя ключ ресурса должен быть уникальным в любом отдельном словаре, ключ может существовать несколько раз в наборе объединенных словарей. В этом случае возвращаемый ресурс будет поступать из последнего словаря, найденного последовательно в коллекции MergedDictionaries. Если коллекция MergedDictionaries была определена в XAML, то порядок объединенных словарей в коллекции - это порядок элементов, как указано в разметке. Если ключ определен в основном словаре, а также в словаре, который был объединен, то возвращаемый ресурс будет исходить из основного словаря. Эти правила области видимости одинаково применяются как к статическим, так и к динамическим ссылкам на ресурсы.

Это означает, что вы можете определить свой базовый скин в другом ResourceDictionary и объединить его с другим ResourceDictionary . Укажите скин User в последнем, и он сначала найдет его, в противном случае он продолжит детализацию до объединенного словаря, который содержит Base. Каждый из ваших пользовательских словарей может объединять базовый словарь, и вы просто загружаете пользовательский словарь в приложение, а не оба отдельно.

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

Вы можете просто назвать свою Base как BaseButtonBg, а когда вы не объединяете основанный на пользователях ResourceDictionary, объединяйте общий, содержащий:

<Style x:Key="ButtonBg" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonBg}"/>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top