Расширение / переопределение стиля в словаре ресурсов - PullRequest
7 голосов
/ 31 июля 2009

У меня есть 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, я мог бы избежать ошибок именования, когда я даю им тот же ключ, но не могу найти никакого способа сделать это. Другими вариантами является принудительная реализация каждого стиля, даже если ничего не изменилось, или программная проверка в скинах, но это последние средства.

Ответы [ 2 ]

10 голосов
/ 31 июля 2009

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

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

Редактировать: У меня есть лучшая информация. От MSDN для объединенных словарей :

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

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

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

0 голосов
/ 31 июля 2009

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

<Style x:Key="ButtonBg" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonBg}"/>
...