WPF: доступ к ресурсам в сборке элемента управления - PullRequest
3 голосов
/ 23 июня 2010

У меня есть элемент управления, для которого я хочу объявить ресурсы в файле xaml. если бы это был пользовательский элемент управления, я мог бы поместить ресурсы в блок <UserControl.Resources> и сослаться на них в коде через this.Resources["myResourceKey"] как мне добиться той же функциональности в элементе управления. на данный момент единственная ссылка на xaml, которая у меня есть, - через статический конструктор элементов управления для ссылки на стиль (и шаблон элемента управления)

static SlimlineSimpleFieldTextBlock() {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimlineSimpleFieldTextBlock), new FrameworkPropertyMetadata(typeof(SlimlineSimpleFieldTextBlock)));
}

, но даже если я добавлю блок в xaml <Style.Resources>, я не смогу ссылаться на них (так как Стиль равен нулю на этапе OnApplyTemplate), и даже если бы я это сделал, это означало бы, если бы кто-то перебил стиль, я потерять мои ресурсы.

1 Ответ

5 голосов
/ 23 июня 2010

Создайте свой ресурсный ключ, используя ComponentResourceKey. Обычные ключи ресурсов ищутся только в визуальном дереве и в ресурсах вашего приложения. Но любой ключ ресурса, который является ComponentResourceKey, также ищется в словаре темы для сборки, содержащей тип. (Это также верно для Type объектов, используемых в качестве ключей ресурсов.)

В вашем Themes / Generic.xaml сборки, содержащей элемент управления «Сэндвич», вы можете иметь:

<SolidColorBrush x:Key="{ComponentResourceKey local:Sandwich, Lettuce}"
                 Color="#00FF00" />

<ControlTemplate x:Key="{ComponentResourceKey local:Sandwich, PeanutButter}" ...>
  ...
</ControlTemplate>

Вы можете ссылаться на эти ресурсы в коде так:

var lettuce = (Brush)FindResource(
                 new ComponentResourceKey(typeof(Sandwich), "Lettuce"));

var penutButter = (ControlTemplate)FindResource(
                 new ComponentResourceKey(typeof(Sandwich), "PeanutButter"));

Вы также можете ссылаться на эти ресурсы в XAML следующим образом:

<Border Background="{StaticResource ResourceKey={ComponentResourceKey local:Sandwich, Lettuce}}" />

Обе эти формы ссылок работают из любого места, где может использоваться FindResource, который находится внутри кода или XAML для любого объекта, производного от FrameworkElement, FrameworkContentElement или Application.

Дополнительные примечания

Алгоритм поиска для ресурса ComponentResourceKey включает в себя только сборку, содержащую указанный тип, а не сам тип. Таким образом, элемент управления типа Soup может использовать ComponentResourceKey {ComponentResourceKey local:Sandwich,Seasonings}, если классы Soup и Sandwich находятся в одной сборке. Пока все в ComponentResourceKey точно совпадает, а ресурс фактически находится в той же сборке, что и данный тип, ресурс будет найден.

Также обратите внимание, что хотя можно использовать pack URI для загрузки ResourceDictionary из другой сборки, это плохая идея. В отличие от решения Themes / Generic.xaml, вам действительно нужно изменить приложение, используя ваши элементы управления, и оно также страдает от проблем множественного включения и переопределения.

Каждый раз, когда вы используете Themes / Generic.xaml, у вас должен быть правильно установлен атрибут ThemeInfoAttribute для этой сборки. Вы можете начать с этого в AssemblyInfo.cs вашей управляющей библиотеки:

[assembly:ThemeInfoAttribute(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
...