2009-04-24 15 views
6

ユーザーは、カラーピッカーダイアログから色を選択してリアルタイムでアプリケーションのスタイルを変更できるようにすることで、アプリケーションをよりカスタマイズ可能にしようとしています(DynamicResourceWPF:ランタイム中にApp.xamlからリソース(色)を変更する

app.xamlにある特定のリソースを変更するにはどうすればよいですか?

var colorDialog = new CustomControls.ColorPickerDialog(); 
var dResult = colorDialog.ShowDialog(); 
var x = Application.Current.Resources.Values.OfType<LinearGradientBrush>().First(); 
x = new LinearGradientBrush(); 
x.GradientStops.Add(new GradientStop(colorDialog.SelectedColor,1)); 

このapp.xamlファイルの抜粋:

<Application.Resources> 
     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="HeaderBackground"> 
      <GradientStop Color="#82cb02" Offset="1"/> 
      <GradientStop Color="#82cb01" Offset="0.2"/> 
      <GradientStop Color="#629a01" Offset="0.5"/> 
     </LinearGradientBrush> 

最善である私は、このしかし運(単なるテスト)のようなものを試してみました


アプリケーションにこの形式のカスタマイズ機能(基本的には色の変更のみ)を許可する方法はありますか?


[更新]

私は頼まれた前の質問からthis answerを見つけ、それを試してみましたが、私は例外Petojが与えられたため、コメントに記載された同じInvalidOperationExceptionがを取得しています回答。ここに答えからのサンプルコードは次のとおりです。

XAML

<LinearGradientBrush x:Key="MainBrush" StartPoint="0, 0.5" EndPoint="1, 0.5" > 
    <GradientBrush.GradientStops> 
     <GradientStop Color="Blue" Offset="0" /> 
     <GradientStop Color="Black" Offset="1" /> 
    </GradientBrush.GradientStops> 
</LinearGradientBrush> 

のC#:

LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush; 
myBrush.GradientStops[0].Color = Colors.Red; 

答えて

13

スキニングをやろうとしているようですね。

リソースディクショナリ内のリソースを別のファイルに定義することをお勧めします。次に、コード内であなたがなるようにリソースをロードすることができます(App.csを変更するには、その後別の場所で、デフォルトをロードする):

//using System.Windows 
ResourceDictionary dict = new ResourceDictionary(); 
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative); 

Application.Current.Resources.MergedDictionaries.Add(dict); 

また、App.xamlで、デフォルトのリソースディクショナリを定義し、コードでそれを単にアンロードすることができ良い。

MergedDictionariesオブジェクトを使用すると、実行時に使用している辞書を変更できます。インターフェイス全体をすばやく変更するという魅力のように機能します。

1

あなたが凍結されたオブジェクトを変更しようとしているので、あなたは例外を取得します。すべてのアプリケーションレベルのリソースは、フリーズ可能でLinearGradientBrushがあれば、自動的にフリーズされます。あなたがウィンドウレベルのような低レベルでそれを追加した場合、それは動作します。

+0

しかし、このスタイルはプロジェクトのすべてのウィンドウに適用されるため、ウィンドウに追加できません。 –

6

は、実行時にアプリケーション全体のリソースを変更するようなものです:

InvalidOperationExceptionが約
Application.Current.Resources("MainBackgroundBrush") = Brsh 

、私はウォールストリートプログラマーが正しいと思います。 既存のブラシを変更するのではなく、必要なすべてのグラデーションストップを含む新しいブラシをコード内に作成し、この新しいブラシをアプリケーションリソースに割り当てる必要があります。

一部GradientStopsの色を変更する別のアプローチは、のようなアプリケーションワイドSolidColorBrushesにDynamicResource参照として、それらの色を定義することである。

<LinearGradientBrush x:Key="MainBrush" StartPoint="0, 0.5" EndPoint="1, 0.5" > 
<GradientBrush.GradientStops> 
    <GradientStop Color="{DynamicResource FirstColor}" Offset="0" /> 
    <GradientStop Color="{DynamicResource SecondColor}" Offset="1" /> 
</GradientBrush.GradientStops> 

、次いで

Application.Current.Resources["FirstColor"] = NewFirstColorBrsh 
Application.Current.Resources["SecondColor"] = NewSecondColorBrsh 

HTH

を使用
+0

これはまさに私が欲しかったものです。 –

+0

これはSilverlightでは動作しません。 'DynamicResource'はサポートされていません。 – mbomb007

2

Clone()方法ブラシ(またはStoryboardのような他のFreezableオブジェクト)の深いコピーを作成し、それを使用する:

LinearGradientBrush myBrush = FindResource("MainBrush") as LinearGradientBrush; 
myBrush = myBrush.Clone(); 
myBrush.GradientStops[0].Color = Colors.Red; 

@WallstreetProgrammerは権利である - すべてのアプリケーションレベルのリソースは、デフォルトで凍結されています。

なぜオブジェクトを最初にクローンする必要があるのですか。

関連する問題