13

定義された列挙型ステータスからブラシにvalueconverterをバインドしようとすると、XAMLデザイナーでエラーが発生します。

「OKStatus」リソースが見つかりません。

アプリケーションは実行時に正常に動作しますが、デザイナーでGUIを表示できません。私のリソースは、実行時に読み取られるcolor.xamlファイルで定義されています。すべてのコードは同じ名前空間内にあります

私のXAML:

xmlns:config = "clr-namespace:App.MyNamespace"

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="c:\Skins\Colors.xaml" />
            <ResourceDictionary Source="c:\Skins\Common.xaml" />                
        </ResourceDictionary.MergedDictionaries>
        <config:StatusConverter x:Key="StateConverter" />
        <config:BoolConverter x:Key="BoolConverter" />
        <config:BooleanConverter x:Key="BooleanConverter" />
    </ResourceDictionary>
</UserControl.Resources>

状態

私のコンバーター:

[ValueConversion(typeof(bool), typeof(Brush))]
public class BoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        bool state = (bool)value;

        FrameworkElement FrameElem = new FrameworkElement();

        if (state == true)
            return (FrameElem.FindResource("OKStatus") as Brush);
        else
            return (FrameElem.FindResource("ErrorStatus") as Brush);
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}

このコードでは、frameElemは私が定義したリソースについての知識を持っていないので、設計中にリソースにアクセスする方法が必要です。これは可能ですか?

4

5 に答える 5

17

はい、可能です。あなたの推測は正しいです。リソースの検索は論理ツリーから始まり、新しいものを作成しFrameworkElement()てもこれは満たされません。完全に切り離されています。

あなたにできること (そして N8 の提案がうまくいかない場合にあなたがしなければならないこと) は、コンバーターに への参照を渡すことUserControlです。FrameworkElementFindResource()

N8の提案がおそらくうまくいかない理由は、Application.Current.FindResource()おそらくアプリケーションレベルのリソースから始まり、次にシステムリソースに行くからですが、あなたが求めているリソースはUserControlのリソースにあります。それらが App.xaml のリソースに配置されていれば、機能します。ただし、設計時にあると思いますApplication.Currentnull

これを行うために私が考えることができる最も簡単な方法は、あなたUserControlのコンストラクターにあります:

public MyUserControl(){
    var boolconv = new BoolConverter(); 
    boolconv.FrameworkElement = this;
    this.Resources.Add( "BoolConverter", boolconv );
    InitializeComponent();
}

InitializeComponent()後ではなく前に行くと確信しています。

DependencyPropertyXAML でこれを行うと、コンバーターに をバインドできるように をコンバーターに追加する必要があるため、より複雑になりますUserControl。それは行き過ぎだと思います。

もう 1 つの方法は、コンバーターTrueBrushFalseBrushプロパティを配置し、それらを XAML に割り当てることです。これは、私のコンバーターが曖昧で一般的な用途になるようにするためによく行う方法です。(注:名前は少し異なります。)

<config:BoolToBrushConverter x:Key="Bool2Brush"
                      TrueBrush="{StaticResource OKStatusBrush}"
                      FalseBrush="{StaticResource ErrorStatusBrush}" />
于 2011-06-01T13:40:16.970 に答える
6

問題は、ビジュアル ツリーにないフレームワーク要素からリソースを見つけようとしていることにあると思います。代わりに次のことを試していただけますか?

Application.Current.FindResource("OKStatus") as Brush;
于 2011-06-01T13:33:20.020 に答える
0

私もこの問題に遭遇しました。Application.Currentからリソースを取得するには、呼び出しが最善の方法だと思います。リソースはIValueConverter、ウィンドウごと、ページごと、またはコントロールごとのレベルで定義されていないからです。これには、前述のように、リソースが少なくともアプリケーション レベルである必要があります。

ただし、Application.Currentデザイナでは参照が null に設定されているため、このメソッドは常にデザイナを壊します。実行中のアプリケーションにコンバーターのリソースへのアクセスを許可している間に、デザイナーが表示する何かが与えられているように見えます。

この問題を抱えている皆さんは、lewi が実装した Kludge を実装する必要はありません。これは、デザイナー サーフェイスを読み込む場合のみです。Application.Current呼び出しには何か関係があるため、実行中のアプリケーションには影響しません。

于 2012-06-04T19:18:28.820 に答える
-1

実際に私が (今のところ) 行ったことは、FindResource から TryFindResource に変更し、文を try/catch ブロックに入れることでした。これはこれまでのところうまくいくようです。

try
{
    if (state == true)
       return (FrameElem.TryFindResource("OKStatus") as Brush);
    else
       return (FrameElem.TryFindResource("ErrorStatus") as Brush);
}

catch (ResourceReferenceKeyNotFoundException)
{
   return new SolidColorBrush(Colors.LightGray);
}
于 2011-06-08T10:48:27.187 に答える