2012-01-07 8 views
6

WPFが時々怒り狂うことがあります。WPFウィンドウとそのユーザーコントロール間でデータを共有する最適な方法は何ですか?

私は、タブコントロールといくつかのタブを含む単一のメインウィンドウで構成されているかなり単純なアプリケーションを持っています。私は、同じファイル内のすべてのタブのコードを持っているという考えが好きではなかったので、this questionの答えを使用して、各タブを別々のユーザーコントロールに分割しました。

私のメインウィンドウの中に、私はアプリケーション設定と他のアプリケーション全体のデータを含むオブジェクトのインスタンスを持っています。いくつかのタブでは、データバインディングの目的でこのデータにアクセスする必要があります。私はこれを達成する良い方法を見つけることができませんでした。

最初に、コントロールのLoadedイベントで親ウィンドウにアクセスしようとしましたが、以下のコードに示すように、設定オブジェクトを公開したメインウィンドウのプロパティへの参照を取得しました。この種の作業は、タブがフォーカスを獲得するたびにロードされたイベントを起動します。また、このイベントはコントロールのライフサイクルの後半に発生するため、ユーザーコントロールのXAMLでこのオブジェクトのプロパティのいずれにもバインドできません。

private void MyUserControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    this.ApplicationSettings = ((MainWindow)Window.GetWindow(this)).ApplicationSettings; 
} 

次に、データをユーザーコントロールのコンストラクタに渡すことを実験しましたが、XAMLでこれを行う方法はありません。

これらがアプリケーション全体の設定であることを考えれば、私はApplicationSettingsクラスをシングルトンにしてどこでも参照することができますが、単体テストの目的ではしません。

このように何を達成するのですか?私のアプローチは根本的に欠陥がありますか?私の考えでは、これらのUI要素はすべて同じウィンドウの一部であるため、メインウィンドウからデータにアクセスできるはずですが、オブジェクトモデルはこれを許可しないように見えます。

答えて

2

あなたはこの例ではSettingsHolder(ラッパークラスの静的プロパティにオブジェクトおよびXAMLで

を介してアプリケーション広い、それを参照する設定を入れることができます:

{Binding SettingName, Source={x:Static local:SettingsHolder.Settings}} 

localは、名前空間、あなたのSettingsHolderているとクラスがある。

コード:

var x = SettingsHolder.Settings.SettingName; 
SettingsHolder.Settings.SettingName = x; 
+0

これは私が取るつもりのルートだと思います。私が元の投稿で言ったように、私は実際のシングルトンなしでシングルトンの動作をしたい、そして、これは私にそれを与える。実際には、おそらくクラスをシングルトンにしますが、テスト目的でコンストラクタを公開しておきます。 ありがとう! – EricTheRed

1

ユーザーコントロールの宣言では、バインドする必要があるすべてのものを含むオブジェクトのインスタンスにデータコンテキストを設定するだけで済みます。

<someNamespace:EricsUserControl DataContext="{Binding InstanceOfBindingObject}"/>

次に、あなたは通常どおり、ユーザーコントロール内にそのオブジェクトのインスタンスのプロパティにアクセスすることができます。

+0

これは本当に知りたいことですが、これを他のものに使うこともできますが、このオプションを開いたままにしておくと、コード内の設定にもアクセスできます。 – EricTheRed

+0

@EricTheRedは完全に賢明ですが、頭を上げるだけで、コード内のユーザーコントロールのDataContextにアクセスすることができます。したがって、上記のようにインスタンスオブジェクトにバインドし、コードビハインドファイル内で 'var myInstance =(BindingObjectClass)this.DataContext'というコードを少し実行した場合、myInstance変数からそのオブジェクトにアクセスできるようになります。将来、いつか助けてくれることを願っています! – Kevek

0

TabにはFrameを使用し、にはPageを置きます。 (しかし私は同じことがユーザーコントロールに適用できると思います)。コンストラクタは、Pageが作成されたときにのみ起動され、ページの作成時を制御してコンストラクタで情報を渡すことができます。ページには、より多くのライフサイクルイベントがあります。私はUIをビルドするためのLoadedイベントも使用します(一度起動するだけです)。 XAMLでページをバインドすると、アプリケーションを起動すると起動し、情報を渡すことはできません。これはページを作成してダイアログに表示しますが、そのページをフレームにバインドすることができます。

 NavigationWindow winSearchXML; 
     using (new WaitCursor()) 
     { 
      winSearchXML = new NavigationWindow(); 
      winSearchXML.Content = new PageSearchResultsXML(GabeLib.GetSearchXML(GabeLib.enumXMLtype.Flat)); 
     } 
     winSearchXML.ShowDialog(); 

私はいくつかの時間が私はちょうど理解していないページ上のライフサイクルを得ることを正直にする必要があります。だから塩の穀物でこれを取る。しかし、要点は、あなたが必要なものを与えるかもしれないコンストラクタとロードされたイベントを持っていることです。

+0

それは賢いです!私はそのようなことをすることは決して考えなかった。私は私が何をしているのかと思うが、これはちょっと残酷だ。しかし、アイデアをありがとう。 – EricTheRed

関連する問題