[解決済み] WinFormsのモデル-ビュー-プレゼンター
質問
WinFormsを使って、初めてMVPメソッドを実装しようとしています。
各レイヤーの機能を理解しようと思っています。
私のプログラムには、クリックするとopenfiledialogウィンドウを開くGUIボタンがあります。
そこでMVPを使用して、GUIはボタンのクリックイベントを処理し、次にpresenter.openfile()を呼び出します。
Presenter.openfile() 内で、そのファイルのオープンをモデル層に委ねるべきか、または処理するデータやロジックがないため、単にリクエストに対処して openfiledialog ウィンドウを開くべきでしょうか?
更新しました。 私はこれに関してさらなる支援を必要とし、できれば私が文脈を持つように、以下の私の特定のポイントに合わせたと感じたので、私は報奨金を提供することを決定しました。
さて、MVPについて読みあさった後、私はパッシブビューを実装することを決定しました。 事実上、私はプレゼンターによって処理される Winform 上のコントロールの束を持っており、その後タスクはモデル (複数可) に委譲される予定です。 私の具体的なポイントは以下のとおりです。
-
winformがロードされるとき、それはツリービューを取得する必要があります。 そのため、ビューは次のようなメソッドを呼び出すべきだと考えていますが、正しいでしょうか: presenter.gettree(), これは順番にモデルに委任し、モデルはツリービューのデータを取得し、それを作成して構成し、プレゼンターに返し、今度はビューに渡して、それを単に、たとえばパネルに割り当てることになります?
-
私はdatagridviewも持っているので、これはWinform上の任意のデータコントロールのために同じでしょうか?
-
私のアプリは、同じアセンブリを持つ多くのモデルクラスを持っています。 また、起動時にロードする必要のあるプラグインを含むプラグインアーキテクチャをサポートしています。 ビューは単純にプレゼンターメソッドを呼び出し、プレゼンターメソッドはプラグインをロードするメソッドを呼び出し、ビューに情報を表示するのでしょうか。 どの層がプラグインの参照を制御するのでしょうか。 ビューがそれらへの参照を保持するのか、それともプレゼンターが保持するのでしょうか?
-
ビューは、ツリービューノードの色からデータグリッドのサイズなど、プレゼンテーションに関するあらゆることを処理するべきだと考えていますが、正しいでしょうか?
これらは私の主な関心事であり、これらのためにフローがどのようにあるべきかを理解すれば、私は大丈夫だと思います。
どのように解決するのですか?
これは、MVPとあなたの具体的な問題についての私の謙虚な考えです。
最初に のように、ユーザーが操作できるもの、あるいは単に表示されるものは、すべて ビュー . このようなビューの法則、動作、特性は インターフェース . そのインターフェイスは WinForms UI、コンソール UI、Web UI、あるいはまったく UI を使用しないで実装することができます (通常、プレゼンターをテストする場合)。
2 番目 の場合、ビューは常に プレゼンター . このようなプレゼンターの法則、振る舞い、特性もまた インターフェース . そのインターフェイスは、そのビューインターフェイスの法則に従う限り、具体的なビューの実装には何の関心も持ちません。
第三に プレゼンターはビューを制御するので、依存関係を最小にするために、ビューがプレゼンターについて全く何も知らないということは、実際には何の利益もありません。プレゼンターとビューの間には合意された契約があり、それはビューインタフェースによって記述されています。
の意味するところは 第三の は
- プレゼンターはビューが呼び出すことのできるメソッドを持っていませんが、ビューはプレゼンターがサブスクライブできるイベントを持っています。
- プレゼンターはそのビューを知っています。私は具象プレゼンターのコンストラクタ注入でこれを達成することを好みます。
- ビューは、どのようなプレゼンターがそれを制御しているのかを知りません; それは単に任意のプレゼンターを提供されることはないでしょう。
あなたの問題に対して、上記はやや簡略化されたコードで次のようになります。
interface IConfigurationView
{
event EventHandler SelectConfigurationFile;
void SetConfigurationFile(string fullPath);
void Show();
}
class ConfigurationView : IConfigurationView
{
Form form;
Button selectConfigurationFileButton;
Label fullPathLabel;
public event EventHandler SelectConfigurationFile;
public ConfigurationView()
{
// UI initialization.
this.selectConfigurationFileButton.Click += delegate
{
var Handler = this.SelectConfigurationFile;
if (Handler != null)
{
Handler(this, EventArgs.Empty);
}
};
}
public void SetConfigurationFile(string fullPath)
{
this.fullPathLabel.Text = fullPath;
}
public void Show()
{
this.form.ShowDialog();
}
}
interface IConfigurationPresenter
{
void ShowView();
}
class ConfigurationPresenter : IConfigurationPresenter
{
Configuration configuration = new Configuration();
IConfigurationView view;
public ConfigurationPresenter(IConfigurationView view)
{
this.view = view;
this.view.SelectConfigurationFile += delegate
{
// The ISelectFilePresenter and ISelectFileView behaviors
// are implicit here, but in a WinForms case, a call to
// OpenFileDialog wouldn't be too far fetched...
var selectFilePresenter = Gimme.The<ISelectFilePresenter>();
selectFilePresenter.ShowView();
this.configuration.FullPath = selectFilePresenter.FullPath;
this.view.SetConfigurationFile(this.configuration.FullPath);
};
}
public void ShowView()
{
this.view.SetConfigurationFile(this.configuration.FullPath);
this.view.Show();
}
}
上記に加え、普段はベースとなる
IView
インターフェースを作成し、そこに
Show()
を格納し、ビューが通常恩恵を受けるオーナービューやビュータイトルを格納します。
あなたの質問に対して
1. winformがロードされるとき、それはツリービューを取得する必要があります。そのため、ビューは次のようなメソッドを呼び出すべきであると考えるのは正しいでしょうか: Presenter.gettree(), これは順番にモデルに委譲し、モデルはツリービューのデータを取得し、それを作成して構成し、プレゼンターにそれを返し、今度はビューに渡して、それを例えばパネルに単に割り当てます?
私なら
IConfigurationView.SetTreeData(...)
からIConfigurationPresenter.ShowView()
への呼び出しの直前でIConfigurationView.Show()
2. datagridviewも持っているので、これはWinform上のどのデータコントロールでも同じでしょうか?
はい、私は
IConfigurationView.SetTableData(...)
を使用します。与えられたデータをフォーマットするのはビュー次第です。プレゼンターは、表形式のデータが欲しいというビューの契約に従うだけです。
3. 私のアプリでは、同じアセンブリを持つモデルクラスがいくつもあります。また、起動時にロードする必要があるプラグインを持つプラグインアーキテクチャをサポートしています。ビューは単純にプレゼンターメソッドを呼び出し、プレゼンターメソッドはプラグインをロードしてビューに情報を表示するメソッドを呼び出すのでしょうか。どの層がプラグインの参照を制御するのでしょうか。ビューがそれらへの参照を保持するのか、それともプレゼンターが保持するのでしょうか?
プラグインがビューに関連するものであれば、ビューはそれらについて知っているべきですが、プレゼンターはそうではありません。もしそれらがすべてデータとモデルに関するものであるなら、ビューはそれらと何の関係もないはずです。
4. ツリービューのノードの色からデータグリッドのサイズなど、表示に関するあらゆることをビューが処理すべきであると考えるのは正しいですか?
プレゼンターがデータを記述したXMLを提供し、ビューがそのデータを受け取り、CSSスタイルシートを適用すると考えてください。具体的には、プレゼンターは
IRoadMapView.SetRoadCondition(RoadCondition.Slippery)
と呼び、ビューが道路を赤色で描画します。
クリックされたノードのデータについてはどうでしょうか?
5. もし私がtreenodesをクリックした場合、私は特定のノードをプレゼンターに渡すべきで、そこからプレゼンターはどのデータが必要かを調べ、ビューにそれを戻す前にそのデータをモデルに要求するのでしょうか?
可能であれば、ビューでツリーを表示するために必要なすべてのデータを一発で渡したいところです。しかし、一部のデータが大きすぎて最初から渡せない場合や、その性質が動的でモデルから (プレゼンターを介して) "最新のスナップショット" を必要とする場合、次のようなものを追加します。
event LoadNodeDetailsEventHandler LoadNodeDetails
のようなものをビューインターフェースに追加し、プレゼンターがそれをサブスクライブし、ノードの詳細をLoadNodeDetailsEventArgs.Node
(にあるノードの詳細をモデルから取得し、イベントハンドラーデリゲートが戻ったときにビューが表示されているノードの詳細を更新できるようにします。データをフェッチすることが良いユーザーエクスペリエンスのために遅すぎるかもしれない場合、この非同期パターンが必要かもしれないことに注意してください。
関連
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】Socket.Selectがエラー "An operation was attempted on something that is not a socket" を返す。
-
[解決済み】"指定されたパスのフォーマットはサポートされていません。"
-
[解決済み】Nullableオブジェクトは値を持たなければならない?
-
[解決済み] なぜList<T>を継承しないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】GDI+、JPEG画像をMemoryStreamに変換する際にジェネリックエラーが発生しました。
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み】C#で四捨五入する方法
-
[解決済み】"The ConnectionString property has not been initialized "を修正する方法
-
[解決済み】Sequence contains no matching element(シーケンスにマッチする要素がない
-
[解決済み】リソースの読み込みに失敗した:ステータス500(内部サーバーエラー)のサーバーの応答)
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】別のスレッドがこのオブジェクトを所有しているため、呼び出し側のスレッドはこのオブジェクトにアクセスできない