Как назначить ресурсы WPF другим тегам ресурсов

Это довольно неясно, я могу просто упустить что-то очень простое.

Сценарий 1

Допустим, я создаю кисть градиента, как это в моем <Window.Resources> раздел:

<LinearGradientBrush x:Key="GridRowSelectedBackBrushGradient" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="#404040" Offset="0.0" />
    <GradientStop Color="#404040" Offset="0.5" />
    <GradientStop Color="#000000" Offset="0.6" />
    <GradientStop Color="#000000" Offset="1.0" />
</LinearGradientBrush>

Тогда гораздо позже я хочу переопределить HighlightBrushKey для DataGrid. Я в основном сделал это так (ужасно);

<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
                     GradientStops="{Binding Source={StaticResource GridRowSelectedBackBrushGradient}, Path=GradientStops}"
                     StartPoint="{Binding Source={StaticResource GridRowSelectedBackBrushGradient}, Path=StartPoint}"
                     EndPoint="{Binding Source={StaticResource GridRowSelectedBackBrushGradient}, Path=EndPoint}" />

Это, очевидно, не самый приятный способ ссылки на ресурс. Я также придумал следующую проблему, которая почти идентична.

Сценарий 2

Скажем, я создал два цвета в моем <Window.Resources> разметка, вот так:

<SolidColorBrush x:Key="DataGridRowBackgroundBrush" Color="#EAF2FB" />
<SolidColorBrush x:Key="DataGridRowBackgroundAltBrush" Color="#FFFFFF" />

Затем я хочу предоставить их в массиве, который передает ConverterParameter в привязку, чтобы я мог предоставить пользовательскому конвертеру мои экземпляры статического ресурса:

<Setter Property="Background">
    <Setter.Value>
        <Binding RelativeSource="{RelativeSource Mode=Self}" 
                 Converter="{StaticResource BackgroundBrushConverter}">
            <Binding.ConverterParameter>
                <x:Array Type="{x:Type Brush}">
                    <SolidColorBrush Color="{Binding Source={StaticResource DataGridRowBackgroundBrush}, Path=Color}" />
                    <SolidColorBrush Color="{Binding Source={StaticResource DataGridRowBackgroundAltBrush}, Path=Color}" />
                </x:Array>
            </Binding.ConverterParameter>
        </Binding>
    </Setter.Value>
</Setter>

Я попытался сделать ссылку на существующий ресурс, но в своих усилиях я фактически воссоздал ресурс и связал свойства так, чтобы они соответствовали. Опять же, это не идеально.

Потому что я решил эту проблему хотя бы дважды, есть ли лучший способ?

Спасибо том

2 ответа

Решение

Мне было интересно, когда кто-то собирался спросить об этом.

Что вы хотите сделать в Сценарии 1, так это эффективно присвоить отдельному ресурсу "псевдоним". Это легко сделать с помощью разметки, которая кажется очевидной только после того, как вы ее увидите. Предположим, у нас есть это в нашем App.xaml или где-то:

<ResourceDictionary>
  <LinearGradientBrush x:Key="GridRowSelectedBackBrushGradient" ... />
</ResourceDictionary>

Чтобы включить псевдоним в другой ResourceDictionary, просто:

<ResourceDictionary>
  <StaticResourceExtension x:Key="{x:Static SystemColors.HighlightBrushKey}"
                           ResourceKey="GridRowSelectedBackBrushGradient" />
</ResourceDictionary>

Это ищет объект кисти в первом ResourceDictionary и добавляет тот же объект ко второму ResourceDictionary под новым ключом. Это также работает в пределах одного ResourceDictionary.

Для вашего сценария 2 решение так же просто:

<Binding.ConverterParameter>
  <x:Array Type="{x:Type Brush}">
    <StaticResourceExtension ResourceKey="DataGridRowBackgroundBrush" />
    <StaticResourceExtension ResourceKey="DataGridRowBackgroundAltBrush" />
  </x:Array>
</Binding.ConverterParameter>

Опять же, фактический Brush объекты, найденные с помощью ResourceKey добавляются непосредственно в Brush[] массив. Ничего нового Brush создано.

Я думаю, что мы все так привыкли использовать StaticResourceExtension с синтаксисом расширения разметки (например, {StaticResource Xyz}) что легко забыть, что он также может использоваться с обычным синтаксисом элемента.

Разметка, с которой вы работаете, недостаточно высока. Вы не создаете LinearGradientBrushВаш первый пример: вы просто ссылаетесь на ресурс. Например:

<DataGrid HighlightBrushKey="{StaticResource GridRowSelectedBackBrushGradient}"  ....

Во втором примере я бы сказал, что вы хотите объявить массив как ресурс:

<x:Array Type="{x:Type Brush}" x:Key="MyArray">
  <SolidColorBrush Color="#EAF2FB" />
  <SolidColorBrush Color="#FFFFFF" />
</x:Array>

И тогда вы можете использовать

<Binding RelativeSource="{RelativeSource Mode=Self}" 
         Converter="{StaticResource BackgroundBrushConverter}"
         ConverterParameter="{Staticresource MyArray}" />
Другие вопросы по тегам