イベント処理のためにWPFのリソースディクショナリの背後にコードを設定することは可能ですか?


147

WPFでリソースディクショナリの背後にコードを設定することは可能ですか?たとえば、ボタンのユーザーコントロールでは、XAMLで宣言します。ボタンクリックのイベント処理コードは、コントロールの背後のコードファイルで実行されます。ボタンを使用してデータテンプレートを作成する場合、リソースディクショナリ内のボタンクリックのイベントハンドラーコードをどのように記述できますか。


1
これを行うための正しい方法は、コマンドを使用することです。また、ボタンを有効または無効にする機能も提供しますが、いくつかの回答でハックの匂いがすることが示唆されている方法で行うこともできます。
アランMulholland 14年

回答:


209

あなたが求めているのは、ResourceDictionaryの分離コードファイルが欲しいということです。完全にこれを行うことができます!実際には、ウィンドウの場合と同じ方法で行います。

MyResourceDictionaryというResourceDictionaryがあるとします。MyResourceDictionary.xamlファイルで、次のようにx:Class属性をルート要素に配置します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="MyCompany.MyProject.MyResourceDictionary"
                    x:ClassModifier="public">

次に、次の宣言を使用して、MyResourceDictionary.xaml.csというコードビハインドファイルを作成します。

namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    { 
       public MyResourceDictionary()
       {
          InitializeComponent();
       }     
       ... // event handlers ahead..
    }
}

これで完了です。メソッド、プロパティ、イベントハンドラーなど、コードの後ろに何でも入れることができます。

== Windows 10アプリ用のアップデート==

そして、UWPで遊んでいる場合に備えて、もう1つ注意する点があります。

<Application x:Class="SampleProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- This will NOT work -->
                <!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->

                <!-- Create instance of your custom dictionary instead of the above source reference -->
                <rd:MyResourceDictionary />

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

7
ageektrappedの答えの補足として:分離コードクラスの完全修飾名をx:Class属性に入れてください。x:Class="MyCompany.MyProject.MySubFolder1.MyResourceDictionary"それ以外の場合、単にx:Class = "MyResourceDictionary"と指定すると、xamlパーサーはクラスを見つけられません。
活力

29
必ず部分クラスの分離コードでデフォルトのコンストラクターを提供し、それがInitializeComponent()を呼び出すことを確認してください。(私の場合、MEFを使用してリソースディクショナリをエクスポートしていました。)
Scott Whitlock

4
投票されたコメントの更新されたコードスニペット。答えを完成させる必要があると感じました。よくある間違い。私は今それをやった:)もしそれが気に入らなければ元に戻す。答えてくれてありがとう。
岐阜

2
(少なくともwp8.1では)これは無効になり、resourcedictionaryが参照するカスタムユーザーコントロールを作成する必要があることに注意してください
Jared

9
また、ResourceDictionaryのXAMLファイルのビルドアクションを「ページ」に設定する必要があります。そうしないと、InitializeComponent()呼び出しはコンパイルされません。(ResourceDictionary XAMLファイルは通常、デフォルトで「Resource」に設定されています。)
user1454265

9

「ageektrapped」に同意しません...部分クラスのメソッドを使用することは良い習慣ではありません。辞書をページから分離する目的は何でしょうか?

コードビハインドから、次を使用してax:Name要素にアクセスできます。

Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}

カスタムコントロールが読み込まれたときにコントロールに接続する場合は、OnApplyTemplateメソッドでこれを行うことができます。これを行うには、OnApplyTemplateをオーバーライドする必要があります。これは一般的な方法であり、スタイルをコントロールから切り離したままにすることができます。(スタイルはコントロールに依存するべきではありませんが、コントロールはスタイルを持つことに依存するべきです)。


7
Phobis私は、辞書をページから分離する目的は、メインページxamlの再利用性と可読性に関するものだと思います。上記の解決策は私にとってもうまくいきました。
cleftheris

5

紀州-これは「一般的に奨励されるべきではない慣習」のように思われるかもしれませんが、これはあなたがそれをしたいと思うかもしれない一つの理由です:

テキストボックスがフォーカスを取得したときの標準的な動作は、コントロールがフォーカスを失ったときと同じ位置にキャレットが配置されることです。アプリケーション全体で、ユーザーが任意のテキストボックスにタブで移動したときにテキストボックスのコンテンツ全体が強調表示されるようにしたい場合は、リソースディクショナリに単純なハンドラーを追加するとうまくいきます。

デフォルトのユーザーインタラクションの動作をそのままの動作とは異なるものにしたい他の理由は、リソースディクショナリのコードビハインドの有力な候補のようです。

アプリケーションの機能に固有のものは、リソースディクショナリの背後にあるコードに含めるべきではないことに完全に同意します。


0

XAMLは、コードを含まないオブジェクトグラフを作成するためのものです。
データテンプレートは、カスタムユーザーオブジェクトを画面に表示する方法を示すために使用されます(リストボックスアイテムの場合など)の動作は、データテンプレートの専門分野の一部ではありません。ソリューションを再描画します...


結論:コードビハインドでリソースdicを使用することをお勧めしますか?私はそれを使用したことがないのではないかと思います。
Shimmy Weitzhandler 2009年

1
私はそうしません-私にはそれは正しくないと思います。辞書は特定のキーの値を返す必要があります。OPの場合、コードをデータテンプレートにバンドルします。別のアプローチを試してみます。たとえば、コマンドモデルを使用します。OPの問題について、diffソルンを推奨するための詳細が必要です。
紀州

1
まったくそう思わない。MVVMでは、コードビハインドが非常に役立つシナリオが1つあります。それは、添付プロパティの開発です。コードビハインドで機能させてから、添付プロパティに移植します。これは、マンハッタンのサイズのブレインがない限り、添付プロパティをゼロから開発するよりもはるかに高速です。
コンタンゴ2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.