2009-03-11 8 views
15

¿Hay alguna manera de redefinir/alias un existente SolidColorBrush (o cualquier otro recurso, en realidad)?Redefine/alias un recurso en WPF?

Caso de ejemplo: Tengo un pincel en un ResourceDictionary externo al que quiero hacer referencia por mi propia clave en lugar de la clave original. No quiero depender de la referencia externa, ya que el pincel real es propenso a cambios en el futuro.

Respuesta

13
<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> 

no quiero ser dependiente de la referencia externa, ya que el cepillo real es propenso a cambiar en el futuro .

Seguirás dependiendo del recurso externo, pero no en tantos lugares.

+0

la única limitación es que no se puede hacer referencia tanto al original como al alias si se utilizan en el mismo diccionario de recursos, ya que se anularán entre sí. supongo que esto se aplica a varios diccionarios que se fusionan en el ámbito de la aplicación. –

+0

A juzgar por la forma en que está formulada la pregunta, él no quiere hacer referencia al original, solo su alias. Hacer referencia al original vencería el propósito de crear el alias. –

+0

Eso funciona. ¡Gracias! – Inferis

4

Usted puede tratar de Tuse la StaticResourceExtension, pero en los diccionarios de recursos globales esto no funciona (extraños errores de compilación y tiempo de ejecución):

<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> 

Para superar este problema, he creado la clase siguiente:

/// <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; } 
} 

Uso:

<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> 
+0

Si trato de usar el alias en alguna parte ... p. Ej. donde MyOtherColor es un alias para un Color con la clave MyColor, luego se queja y dice "Tipo de recurso no válido: tipo esperado es 'Color', tipo real es 'Alias' ". –

+0

Para aclarar, funciona si el alias está en un diccionario de recursos, y el alias se usa fuera de ese diccionario. Sin embargo, no se puede usar dentro del mismo diccionario. –

+0

Y los errores espurios se generan y desaparecen según mi comentario original. Si ejecuto la aplicación con éxito, edito el XAML agregando espacios en blanco, aparece un error de compilación.Construyo el proyecto, todavía está allí. Construyo de nuevo, desaparece. ¡Es muy frustrante porque tu idea parecía tan prometedora! –

2

tengo una actualización de 012.338.solución. Esto funciona para recursos dentro del mismo diccionario de recursos y en cualquier lugar dentro de la aplicación.

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; 
    } 
} 

El uso es similar al anterior, pero la clave es usar Alias como la extensión de marcado cuando se usa, no StaticResource. En algún lugar de la pila de recursos de aplicaciones, definir los recursos ...

<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> 

Y donde quiera que estés referencia a los alias ...

<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> 

Mi solución requiere hacer referencia a las cadenas, pero funciona para cualquier objeto quieres alias

Cuestiones relacionadas