2009-03-11 39 views
15

既存のSolidColorBrush(または他のリソース)を再定義/エイリアスする方法はありますか?WPFのリソースを再定義/エイリアス?

ケース・イン・ポイント:元のキーの代わりに自分のキーで参照したい外部ResourceDictionaryにブラシがあります。実際のブラシは将来変更される傾向があるので、私は外部参照に依存したくありません。

答えて

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> 

実際 ブラシは 将来的に変更する傾向があるので、私は、 外部基準に依存するようにしたくありません。

あなたは依然として外部リソースに依存していますが、多くの場所には依存しません。

+0

唯一の制限は、同じリソースディクショナリ内で使用されている場合は、元の名前と別名の両方を参照することができないため、互いに上書きされるためです。私はあなたがアプリケーションのスコープでマージする複数の辞書にこれが当てはまると仮定しています。 –

+0

質問の言葉によると、彼はオリジナルを参照したくない - 彼のエイリアスのみ。オリジナルを参照すると、エイリアスを作成する目的が無効になります。 –

+0

それは動作します。ありがとう! – Inferis

4

あなたはStaticResourceExtensionをtuseしようとすることができますが、グローバルリソースディクショナリで、これは(奇妙なコンパイラとランタイムエラーを)動作しません。

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

エイリアスをどこかで使用しようとすると...たとえば、 ここで、MyOtherColorはMyColorキーを持つColorのエイリアスで、「無効なリソースタイプです:予想されるタイプは 'Color' 「エイリアス」です。 –

+0

明示するために、エイリアスがリソースディクショナリにあり、そのエイリアスがそのディクショナリの外側で使用されている場合は動作します。ただし、同じ辞書内では使用できません。 –

+0

偽のエラーは私の元のコメントに従って上げられ、消えます。アプリケーションを正常に実行し、空白を追加してXAMLを編集すると、コンパイラエラーが表示されます。私はプロジェクトをビルドしますが、まだそこにあります。私はもう一度ビルドして、それは消える。あなたのアイデアはとても有望だったので、とてもイライラしています! –

2

私はにアップデートを持っています溶液。これは、同じリソースディクショナリ内のリソースとアプリケーション内の任意の場所の両方のリソースに対して機能します。

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

使用量は上記と同様であるが、キーはStaticResource、使用される場合、マークアップ拡張としてAliasを使用しないことです。どこかのアプリケーション・リソース・スタックで、...

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

私のソリューションは、文字列を参照する必要が、それは任意のオブジェクトのために働きますあなたはエイリアスにしたい。

関連する問題