2009-03-11 13 views
15

C'è un modo per ridefinire/alias uno esistente SolidColorBrush (o qualsiasi altra risorsa, in realtà)?Ridefinisci/alias una risorsa in WPF?

Caso in questione: ho un pennello in un ResourceDictionary esterno che voglio fare riferimento con la mia chiave invece della chiave originale. Non voglio dipendere dal riferimento esterno, poiché il pennello effettivo è soggetto a modifiche in futuro.

risposta

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> 

Non voglio essere dipendente dal riferimento esterno , dal momento che l'attuale pennello è incline a cambiare in futuro.

Continuerai a dipendere dalla risorsa esterna, ma non in altrettanti luoghi.

+0

l'unica limitazione a questo è che non è possibile fare riferimento sia all'originale che all'alias se utilizzato all'interno dello stesso dizionario di risorse, poiché si sovrascriveranno l'un l'altro. sto assumendo che questo si applica a più dizionari si fondono allo scopo di applicazione. –

+0

A giudicare dal modo in cui la domanda è formulata, non vuole fare riferimento all'originale - solo il suo alias. Il riferimento all'originale avrebbe vanificato lo scopo di creare l'alias. –

+0

Questo funziona. Grazie! – Inferis

4

Si può cercare di Tuse lo StaticResourceExtension, ma nei dizionari risorse globali questo non funziona (strani errori di compilazione e di runtime):

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

Per superare questo problema, ho creato la seguente classe:

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

Usage:

<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

Se provo a usare l'alias da qualche parte ... ad es. dove MyOtherColor è un alias per un colore con chiave MyColor, quindi si lamenta e dice "Tipo di risorsa non valido: il tipo previsto è 'Colore', tipo effettivo è "Alias" ". –

+0

Per chiarire, funziona se l'alias si trova in un dizionario risorse e l'alias viene utilizzato al di fuori del dizionario. Tuttavia, non può essere utilizzato all'interno dello stesso dizionario. –

+0

E gli errori spuri vengono generati e scompaiono come nel mio commento originale. Se eseguo correttamente l'app, quindi modifica XAML aggiungendo spazi bianchi, viene visualizzato un errore del compilatore.Costruisco il progetto, è ancora lì. Costruisco di nuovo, scompare. È molto frustrante perché la tua idea sembrava così promettente! –

2

ho un aggiornamento per 012.338.931 Soluzione. Funziona per risorse sia all'interno dello stesso dizionario risorse che in qualsiasi punto dell'applicazione.

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

L'utilizzo è simile al precedente, ma la chiave è di usare Alias come estensione di markup se utilizzati, non StaticResource. Da qualche parte nella pila risorsa applicazione, definire le risorse ...

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

E ovunque si sta riferimento gli 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> 

La mia soluzione necessaria referenziali, ma funziona per qualsiasi oggetto vuoi alias.

Problemi correlati