2016-08-08 5 views
-1

私はこれを理解できません。だから私はできるだけ自分の問題を説明しようとします。ビューモデル間でデータを渡す

MVVMパターンを使用してアプリケーションを構築しています。私はデータモデルCDataClassを埋めるために使用されるビューモデルAAAViewModelでユーザーコントロールAAAViewを持っています。私もメインウィンドウMainViewとそのビューモデルMainViewModelを持っています。次に、ウィンドウDialogViewDialogViewModelがあります。

だからMainViewModel(独自のユーザーコントロールがある)はDialogViewModel(ユーザーコントロールの別のインスタンスを使用)を作成します。これら2つのユーザーコントロールの間でCDataClassのデータを転送するにはどうすればよいですか?私はMainViewModelまたはDialogViewModelのインスタンスを保持するAAAViewModelのプロパティを作成しようとしました。そのため、データを渡すことができますが、依存プロパティとして作成できなかったためスタックしました。

Image representation of problem

私の目標は、下地のCDataClassに異なるデータを持つことができるさまざまなビューで使用可能なユーザーコントロールを作成することです。

私はユーザーコントロールを<views:GeneralInfoView Grid.Row="0" />として使用していますが、異なるユーザーコントロールの2つの異なるインスタンス間でデータを共有する方法はわかりません。いくつかのパターンや方法を指摘すれば、非常に感謝しています。

ありがとうございました。

+0

CDataClassのデータが2つのビューの間で異なる場合、それらは基本的に別々のインスタンスですか? – Steve

+0

http://stackoverflow.com/q/3801681/2470362 –

答えて

1

アプリケーションアーキテクチャをビュー間の関係として図化しているとは思えません。私は、それを考える良い方法は、必要に応じてツリーから垂れ下がったビューを使って、ビューモデル間の関係のセットとして考えることです。そのように考えると、「データはどのように受け継がれますか」がずっと簡単になります。ビューは、ビューモデルとユーザーの間の単なる導管です。あなたは窓と電話のセットとして家を設計しておらず、そこから床の計画を見つけようとします。あなたはその家が何をし、どのように住んでいるのかで始まります。

だから、これは簡単です:

一部のviewmodelsがAAViewModel性質を持っています。これらのビューモデルには、あらゆる種類のシンプルまたは複雑なビューが存在する場合があります。ビューがユーザーにビューモデルのAAViewModelのものを編集させたい場合は、AAViewがビューモデルのAAViewModelに適切にバインドされています。 MainViewModelDialogViewModelはどちらも、誰かが自分のVMのAAViewModelのものを編集できるようにしたい、非常に複雑なインタラクティブなビューです。

MainViewModelDialogViewModelの親であるか、単にモーダルダイアログに入れてDialogViewModelの一時的なインスタンスを作成した場合は、その後、MainViewModelは、ダイアログを表示し、それをどうするかを決定するdialogVM.AAVM.CData.IsDirtyを見て必要があります。または、dialogVM.AAVMに新しいCDataClassインスタンスを表示してから(おそらくそれ自身のインスタンスのクローン)、ShowModel()trueを返した場合は、dialogVM.AAVM.CDataで何かを行います。

ポイントは、あなたのビューモデルがすべてを駆動すると、お互いに通信するのが比較的簡単になるということです。親子は簡単です:親は子どもに物を与え、子どもが何をもたらすのかを見ます。ビューモデルは、別のビューモデルのPropertyChangedイベントをサブスクライブできます。親ビューモデルはその子を監視することができます。子供に何かが起こると、親は兄弟を更新するかどうかを決定することができます。一般的に、子供は親について何も知ってはいけません。異種のコンテキストで子ビューモデルを再利用する方がずっと簡単です。保護者は、その情報をどうするかを決める必要があります。

すべてのAAVi​​ewModelは、誰かが彼にCDataClassのコピーを渡したことを知っています。彼はそれに応じて彼の公共財産を更新する。それから、他の誰か(おそらくAAViewだが彼は知らない)は彼の特性を設定することによって彼にいくつかの変更を渡す。それに応じてCDataClassインスタンスを更新します。しばらくして、彼に知られていない、1つのビューモデルまたは別のものが来て、それを見て、CDataClassを見てください。

ビューとビューモデル間の通信はバインディングを介して行われます。

UPDATE

それはあなたのビューでのviewmodelsを作成していることが判明し、その結果として、あなたは親が彼らに取得することができますか見当がつかない。そして、あなたは、なぜそうした方法で子ビューのビューモデルを作成するのが良い考えではないかを知っています。

は、ここでは、私は上記のviewmodel中心の設計で子ビュー/のviewmodels行う方法は次のとおりです。

まず、ビュー内の子のviewmodelsを作成するためにやっているものは何でも取り除きます。

次に、子ビューモデルタイプのDataTemplateを作成します。これはApp.xamlのリソースにマージされたリソースディクショナリに入れなければなりませんが、怠け者になって2つの異なるビューのうちResourcesに貼り付けるだけで、あなたを殺しません。

あなたの名前空間宣言がどのようなものかわかりません。ビューはxmlns:view="..."と呼ばれ、ビューモデルはxmlns:vm="..."という名前であると仮定します。今

<DataTemplate DataType="{x:Type vm:AAAViewModel}"> 
    <view:AAAView /> 
</DataTemplate> 

、あなたは(そしてそれはそれらのほとんどです)ContentControlから継承する任意のコントロールのContentPropertyAAAViewModelを割り当てることができ、およびテンプレートがインスタンス化されます。つまり、XAMLはAAAViewを作成し、そのインスタンスAAAViewModelを、作成したばかりのAAAViewDataContextプロパティに割り当てます。

次に、子供AAAViewModelを作成してから、それをUIに表示します。

public class DialogViewModel 
{ 

    // You can create this in DialogViewModel's constructor if you need to 
    // give it parameters that won't be known until then. 
    private AAAViewModel _aaavm = new AAAViewModel(); 
    public AAAViewModel AAAVM 
    { 
     get { return _aaavm; } 
     protected set { 
      _aaavm = value; 
      OnPropertyChanged(nameof(AAAVM)); 
     } 
    } 

そして今、我々はDialogViewAAAVMを表示することができます。

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <ContentControl 
     Content="{Binding AAAVM}" 
     Grid.Row="0" 
     /> 

    <StackPanel Orientation="Vertical" Grid.Row="1"> 
     <!-- Other stuff --> 
    </StackPanel> 
</Grid> 

MainViewModelDialogViewModelと連絡を取るんか?ダイアログの場合は、寿命が限られているため、独自のビューモデルを作成することは実際には大したことではありません。どちらにしてもかまいません。私は、以下の2番目の例のように、自分自身を作成することに向かって傾いています。

全く同じではありませんが、近いです。最初に、もう一度、ダイアログが独自のビューモデルを作成する場所で何をしているのかを取り除きます。

MainViewModel。cs

public CDataClass CDC { /* you know the drill */ } 

public void ShowDialog() 
{ 
    var dvm = new DialogViewModel(); 

    // Maybe this isn't what you want; I don't know what CDataClass does. 
    // But I'm assuming it has a copy constructor. 
    dvm.AAAVM.CDC = new CDataClass(this.CDC); 

    if (DialogView.ShowDialog(dvm).GetValueOrDefault()) 
    { 
     CDC = dvm.CDC; 
    } 
} 

この次はviewmodelではなく、viewcodebehindです。

DialogView.xaml.cs

public static bool? ShowDialog(DialogViewModel dvm) 
{ 
    var vw = new DialogView() { DataContext = dvm }; 

    return vw.ShowDialog(); 
} 

、あなたダイアログは、独自のviewmodelの作成を続行しましょう可能性があり、

DialogView.xaml.cs

public static bool? ShowDialog(CDataClass cdc) 
{ 
    var dlg = new DialogView(); 

    dlg.ViewModel.AAAVVM.CDC = cdc; 

    return dlg.ShowDialog(); 
} 

そして親が相互作用することもできます。このような

public DialogViewModel ViewModel => (DialogViewModel)DataContext; 

そして、ShowDialogメソッド:その場合、あなたはそれをこのような公共の財産を与えるだろうその代わりに、このような:

MainViewModel.cs

public void ShowDialog() 
{ 
    var cdcClone = new CDataClass(this.CDC); 

    if (DialogView.ShowDialog(cdcClone).GetValueOrDefault()) 
    { 
     CDC = cdcClone; 
    } 
} 

素敵できちんとしています。

このダイアログがモーダルでない場合は、ダイアログviewmodelをMainViewModelのプライベートメンバーにして、ダイアログのビューを維持するために、ダイアログビューモデルのイベントにサブスクライブするMainViewModelを持っています。ユーザーがダイアログのコピーCDataClassを更新するたびに、ダイアログでDataClassUpdatedが呼び出され、MainViewModelには_dialogViewModel.AAAVM.CDCでスニッファするそのイベントのハンドラがあり、その処理方法が決まります。必要に応じてサンプルコードを入手することができます。

これで、親/子ビューモデルに関してすべてを構築し、必要に応じてビューにそれらを埋め込むことができます。

+0

私はそれを得ました。しかし、AAAViewModelにアクセスできない場合は、どうすればAAAViewModelから取得できますか? AAAViewModelは、コードではなく、ビューで自動的に作成されます。ユーザーコントロールビューはxamlのDialogViewでとして定義されていますので、DialogViewModelの背後にあるviewmodelにどうやってアクセスすればいいのか分かりません。 – benderto

+0

@bendertoそういうわけで、あなたはあなたのビューモデルをそのように作成しません!私が1時間か2時間でオフィスに入ると、それをDataTemplateとしてどのように行うかを示します。 –

+0

@benderto更新された回答。 –

関連する問題