現在、Microsoft MVVMテンプレートを使用していますが、詳細な例が不足していることがイライラしています。付属のContactBookの例では、コマンドの処理がほとんど示されていません。他の例は、概念が類似しているが少し異なるアプローチを使用し、複雑さのないMSDN Magazine記事からのものです。少なくとも基本的なCRUD操作とダイアログ/コンテンツの切り替えを示すまともなMVVMの例はありますか?
みんなの提案は本当に役に立ちました。良いリソースのリストを編集し始めます
Frameworks/Templates
有用な記事
スクリーンキャスト
追加ライブラリ
残念なことに、すべてを実行する優れたMVVMサンプルアプリはありません。また、物事を行うためのさまざまなアプローチがあります。まず、依存性注入、コマンド、イベント集約などの便利なツールを提供して、自分に合ったさまざまなパターンを簡単に試すことができるため、そこにあるアプリフレームワークの1つに慣れておくとよいでしょう(Prismはまともな選択です)。 。
プリズムリリース:
http://www.codeplex.com/CompositeWPF
かなりまともなサンプルアプリ(株式トレーダー)に加えて、多数の小さなサンプルとその方法が含まれています。少なくとも、MVVMを実際に機能させるために人々が使用するいくつかの一般的なサブパターンの良いデモンストレーションです。 CRUDとダイアログの両方の例があります。
Prismは必ずしもすべてのプロジェクトに適しているわけではありませんが、慣れるのは良いことです。
CRUD: この部分は非常に簡単です。WPFの双方向バインディングを使用すると、ほとんどのデータを本当に簡単に編集できます。本当のトリックは、UIを簡単にセットアップできるモデルを提供することです。少なくとも、ViewModel(またはビジネスオブジェクト)がINotifyPropertyChanged
を実装してバインディングをサポートし、プロパティをUIコントロールに直接バインドできることを確認する必要がありますが、IDataErrorInfo
を実装することもできます。検証用。通常、何らかのORMソリューションを使用する場合、CRUDのセットアップは簡単です。
この記事では、単純なcrud操作について説明します。 http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx
LinqToSql上に構築されていますが、例とは無関係です。重要なのは、ビジネスオブジェクトがINotifyPropertyChanged
(LinqToSqlによって生成されるクラスが実装する)を実装することだけです。 MVVMはその例のポイントではありませんが、この場合は重要ではないと思います。
この記事では、データ検証について説明します
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
繰り返しますが、ほとんどのORMソリューションはIDataErrorInfo
を既に実装しているクラスを生成し、通常、カスタム検証ルールを簡単に追加できるメカニズムを提供します。
ほとんどの場合、ORMによって作成されたオブジェクト(モデル)を取得し、それを保持するViewModelに保存し、保存/削除のコマンドを実行できます。これで、UIをモデルのプロパティに直接バインドする準備ができました。
ビューは次のようになります(ViewModelには、ORMで作成されたクラスのように、モデルを保持するItem
プロパティがあります):
_<StackPanel>
<StackPanel DataContext=Item>
<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
<Button Command="{Binding SaveCommand}" />
<Button Command="{Binding CancelCommand}" />
</StackPanel>
_
ダイアログ: ダイアログとMVVMは少し注意が必要です。私はダイアログでMediatorアプローチのフレーバーを使用することを好みます。このStackOverflowの質問でそれについてもう少し読むことができます:
WPF MVVMダイアログの例
私の通常のアプローチは、非常に古典的なMVVMではありませんが、次のように要約できます。
コミットアクションとキャンセルアクションのコマンド、ダイアログを閉じる準備ができたことをビューに知らせるイベント、およびすべてのダイアログで必要なものを公開するダイアログViewModelの基本クラス。
ダイアログの汎用ビュー-これはウィンドウまたはカスタムの「モーダル」オーバーレイタイプコントロールです。基本的には、ビューモデルをダンプするコンテンツプレゼンターであり、ウィンドウを閉じるための配線を処理します。たとえば、データコンテキストの変更時に、新しいViewModelが基本クラスから継承されているかどうかを確認できます。関連する終了イベントにサブスクライブします(ハンドラーはダイアログ結果を割り当てます)。別のユニバーサルクローズ機能(たとえば、Xボタン)を提供する場合は、ViewModelでも関連するクローズコマンドを必ず実行する必要があります。
ViewModelsのデータテンプレートを提供する必要がある場合、特に各ダイアログのビューが個別のコントロールにカプセル化されているため、ViewModelsは非常にシンプルになります。 ViewModelのデフォルトのデータテンプレートは、次のようになります。
_<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}">
<views:AddressEditView DataContext="{Binding}" />
</DataTemplate>
_
ダイアログビューはこれらにアクセスする必要があります。そうしないと、ViewModelを表示する方法がわからないため、共有ダイアログUIを除き、その内容は基本的に次のとおりです。
_<ContentControl Content="{Binding}" />
_
暗黙のデータテンプレートはビューをモデルにマップしますが、誰がそれを起動しますか?
これはnot-so-mvvmの部分です。それを行う1つの方法は、グローバルイベントを使用することです。私が行うべきより良いことは、依存性注入によって提供されるイベントアグリゲータータイプのセットアップを使用することです-このように、イベントはアプリ全体ではなくコンテナに対してグローバルです。 Prismは、コンテナのセマンティクスと依存性の注入に統一フレームワークを使用しており、全体としてUnityがかなり好きです。
通常、ルートウィンドウがこのイベントをサブスクライブすることは理にかなっています。ダイアログを開き、発生したイベントで渡されるViewModelにデータコンテキストを設定できます。
このように設定すると、ViewModelsはアプリケーションにダイアログを開き、UIについて何も知らずにそこでユーザーアクションに応答するように要求できるため、MVVMの機能の大部分は完全なままです。
ただし、UIでダイアログを表示する必要がある場合があり、これにより状況が少し複雑になります。たとえば、ダイアログの位置が、それを開くボタンの位置に依存する場合を考慮してください。この場合、ダイアログを開くときにUI固有の情報が必要になります。通常、ViewModelと関連するUI情報を保持する別のクラスを作成します。残念ながら、そこではいくつかのカップリングが避けられないようです。
要素の位置データを必要とするダイアログを表示するボタンハンドラーの擬似コード:
_ButtonClickHandler(sender, args){
var vm = DataContext as ISomeDialogProvider; // check for null
var ui_vm = new ViewModelContainer();
// assign margin, width, or anything else that your custom dialog might require
...
ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel()
// raise the dialog show event
}
_
ダイアログビューは位置データにバインドし、含まれるViewModelを内部ContentControl
に渡します。 ViewModel自体はまだUIについて何も知りません。
一般に、ShowDialog()
メソッドのDialogResult
returnプロパティを使用したり、ダイアログが閉じられるまでスレッドがブロックすることを期待していません。非標準のモーダルダイアログは常にそのように機能するとは限りません。また、複合環境では、イベントハンドラーが実際にそのようにブロックすることは望ましくありません。 ViewModelでこれを処理できるようにします。ViewModelの作成者は、関連するイベントをサブスクライブしたり、コミット/キャンセルメソッドを設定したりできるので、このUIメカニズムに依存する必要はありません。
したがって、このフローの代わりに:
_// in code behind
var result = somedialog.ShowDialog();
if (result == ...
_
私が使う:
_// in view model
var vm = new SomeDialogViewModel(); // child view model
vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit
vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional)
// raise dialog request event on the container
_
私のダイアログのほとんどはノンブロッキングの擬似モーダルコントロールであり、この方法でそれを行うことは、それを回避するよりも簡単なようだからです。単体テストも簡単です。
Jason Dolingerは、MVVMの優れた screencast を作成しました。 Egorが述べたように、良い例はありません。彼らはすべて終わった。ほとんどは適切なMVVMの例ですが、複雑な問題に直面したときはそうではありません。誰もが独自の方法を持っています。 Laurent Bugnionには、ビューモデル間で通信するための優れた方法もあります。 http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx Cinchも良い例です。 Paul Stovelの優れた post には、彼のMagellanフレームワークでも多くのことが説明されています。
これが便利だとわかりました。コードもあります。
Caliburn を見ましたか? ContactManagerサンプルには、多くの優れた機能が含まれています。汎用WPFサンプルは、コマンドの概要も提供します。ドキュメントはかなり良く、フォーラムは活発です。オススメ!
私もあなたの欲求不満を共有しました。私はアプリケーションを書いていますが、次の3つの要件がありました。
私が見つけたのはほんの一部でしたので、できる限り最高のものを書き始めました。少し話をした後、リファレンスアプリケーションを使用できる他の人(自分のような)がいるかもしれないことに気づいたので、汎用のものをWPF/MVVMアプリケーションフレームワークにリファクタリングし、LGPLでリリースしました。名前は SoapBox Core です。ダウンロードページにアクセスすると、小さなデモアプリケーションが付属しており、そのデモアプリケーションのソースコードもダウンロードできます。それが役立つことを願っています。また、詳細情報が必要な場合は、scott {at} soapboxautomation.comにメールしてください。
[〜#〜] edit [〜#〜]:また、 CodeProjectの記事 がどのように機能するかを説明しています。
ここで、WPF(Inventory Management App)アプリケーションのリンクを追加しています。これはMVVMアーキテクチャ私が設計しました。
そのUIは素晴らしいです。 https://github.com/shivam01990/InventoryManagement
Cinch framework のサンプルプロジェクトは、基本的なCRUDとナビゲーションツールを示しています。 MVVMを使用した非常に良い例であり、その使用法と動機を説明する マルチパート記事 が含まれています。
ここにリンク MVVM WPFステップバイステップ のコードプロジェクトの最初から簡単なMVVMの例を書いています。シンプルな3層アーキテクチャから始まり、PRISMのようなフレームワークを使用するために卒業します。
問題を自分の手に取るまで、私もフラストレーションを共有しました。 IncEditorを開始しました。
IncEditor( http://inceditor.codeplex.com )は、WPF、MVVM、およびMEFを開発者に紹介しようとするエディターです。私はそれを開始し、「テーマ」のサポートのようないくつかの機能を取得することができました。私はWPF、MVVM、またはMEFの専門家ではないため、多くの機能を追加することはできません。私のようなナッターがよりよく理解できるように、私はそれをより良くするために皆さんに誠実な要求をします。