Переопределить / псевдоним ресурс в WPF? - PullRequest
17 голосов
/ 11 марта 2009

Есть ли способ переопределить / псевдоним существующего SolidColorBrush (или любого другого ресурса, на самом деле)?

Показательный пример: у меня есть кисть во внешнем ResourceDictionary, на которую я хочу ссылаться своим собственным ключом вместо исходного ключа. Я не хочу зависеть от внешней ссылки, так как реальная кисть подвержена изменениям в будущем.

Ответы [ 3 ]

14 голосов
/ 11 марта 2009
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="SomeExternalResource">Red</SolidColorBrush>
    </Window.Resources>
    <Grid>
        <Grid.Resources>
            <StaticResourceExtension ResourceKey="SomeExternalResource" x:Key="SomeAliasedResource"/>
        </Grid.Resources>

        <Border Background="{StaticResource SomeAliasedResource}"/>
    </Grid>
</Window>

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

Вы по-прежнему будете зависеть от внешнего ресурса, но не во многих местах.

4 голосов
/ 22 сентября 2011

Вы можете попробовать использовать StaticResourceExtension, но в глобальных словарях ресурсов это не работает (странные ошибки компилятора и времени выполнения):

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

    <SolidColorBrush x:Key="StatusColor_OK" Color="#ff32a248" />
    <StaticResourceExtension
        x:Key="AliasKey"
        ResourceKey="StatusColor_Error" />
</ResourceDictionary>

Чтобы преодолеть эту проблему, я создал следующий класс:

/// <summary>
/// Defines an Alias for an existing resource. Very similar to 
/// <see cref="StaticResourceExtension"/>, but it works in
///  ResourceDictionaries
/// </summary>
public class Alias: System.Windows.Markup.MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        IRootObjectProvider rootObjectProvider = (IRootObjectProvider)
            serviceProvider.GetService(typeof (IRootObjectProvider));
        if (rootObjectProvider == null) return null;
        IDictionary dictionary =  rootObjectProvider.RootObject as IDictionary;
        if (dictionary == null) return null;
        return dictionary[ResourceKey];
    }


    public object ResourceKey { get; set; }
}

Использование:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

    <SolidColorBrush x:Key="StatusColor_OK" Color="#ff32a248" />
    <Alias
        x:Key="AliasKey"
        ResourceKey="StatusColor_Error" />
</ResourceDictionary>
3 голосов
/ 14 мая 2014

У меня есть обновление для решения Ruedi . Это работает для ресурсов в одном словаре ресурсов и в любом месте приложения.

public class Alias : MarkupExtension
{
    public string ResourceKey { get; set; }

    public Alias()
    {

    }
    public Alias(string resourceKey)
    {
        ResourceKey = resourceKey;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return _ProvideLocalValue(serviceProvider) ?? _ProvideApplicationValue();
    }

    private object _ProvideLocalValue(IServiceProvider serviceProvider)
    {
        var rootObjectProvider = (IRootObjectProvider)
            serviceProvider.GetService(typeof(IRootObjectProvider));
        if (rootObjectProvider == null) return null;
        var dictionary = rootObjectProvider.RootObject as IDictionary;
        if (dictionary == null) return null;
        return dictionary.Contains(ResourceKey) ? dictionary[ResourceKey] : null;
    }

    private object _ProvideApplicationValue()
    {
        var value = Application.Current.TryFindResource(ResourceKey);
        return value;
    }
}

Использование аналогично приведенному выше, но ключ должен использовать Alias в качестве расширения разметки, где используется, а не StaticResource. Где-нибудь в стеке ресурсов приложения определите ресурсы ...

<Application x:Class="WPF.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:system="clr-namespace:System;assembly=mscorlib"
             xmlns:wpf="clr-namespace:WPF"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <system:String x:Key="Text">Display some text.</system:String>
        <system:String x:Key="Other">4</system:String>
        <wpf:Alias x:Key="Alias" ResourceKey="Text"/>
        <wpf:Alias x:Key="Second" ResourceKey="Other"/>
    </Application.Resources>
</Application>

И где бы вы ни ссылались на псевдонимы ...

<Window x:Class="WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpf="clr-namespace:WPF"
        Title="MainWindow" Height="150" Width="300">
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="{wpf:Alias Alias}"/>
        <TextBlock Text="{wpf:Alias Second}"/>
    </StackPanel>
</Window>

Мое решение требовало ссылки на строки, но оно работает для любого объекта, который вы хотите псевдоним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...