これは、MVPとあなたの特定の問題に対する私の謙虚な見方です。
まず、ユーザーが操作したり、表示したりできるものはすべてビューですです。このようなビューの法則、動作、および特性は、インターフェースによって記述されます。そのインターフェースは、WinForms UI、コンソールUI、Web UIを使用して実装することも、UIをまったく使用しないこともできます(通常、プレゼンターをテストする場合)。ビューインターフェースの法則に従う限り、具体的な実装は問題ではありません。 。
次に、ビューは常にプレゼンターによって制御されます。このようなプレゼンターの法律、行動、特性は、インターフェースます。そのインターフェースは、そのビューインターフェースの法則に従う限り、具体的なビューの実装には関係ありません。
第三に、プレゼンターはビューを制御するため、依存関係を最小限に抑えるために、ビューにプレゼンターについての知識をまったく持たせても、実際には利益はありません。プレゼンターとビューの間で合意された契約があり、それはビューインターフェースによって示されます。
サードの影響は次のとおりです。
- プレゼンターには、ビューが呼び出すことができるメソッドはありませんが、ビューには、プレゼンターがサブスクライブできるイベントがあります。
- プレゼンターはその見方を知っています。具体的なプレゼンターでコンストラクターインジェクションを使用してこれを実現することを好みます。
- ビューには、どのプレゼンターがそれを制御しているかはわかりません。プレゼンターに提供されることはありません。
あなたの問題では、上記は多少簡略化されたコードでは次のようになります:
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. データグリッドビューも持っているので、これはWinformのどのデータコントロールでも同じですか?
はい、電話します IConfigurationView.SetTableData(...)
。与えられたデータをフォーマットするのはビュー次第です。プレゼンターは、表形式のデータが必要であるというビューの規約に従います。
3. 私のアプリには、同じアセンブリを持つモデルクラスがいくつかあります。また、起動時にロードする必要があるプラグインを備えたプラグインアーキテクチャもサポートしています。ビューは単にプレゼンターメソッドを呼び出し、プラグインをロードしてビューに情報を表示するメソッドを呼び出しますか?その後、どの層がプラグイン参照を制御します。ビューは彼らまたはプレゼンターへの参照を保持しますか?
プラグインがビューに関連している場合、ビューはそれらを認識している必要がありますが、プレゼンターは認識していません。それらがすべてデータとモデルに関するものである場合、ビューはそれらとは何の関係もないはずです。
4. ビューは、treeviewノードの色からデータグリッドのサイズなど、プレゼンテーションに関するすべてのことを処理するべきだと考えるのは正しいですか?
はい。これは、データを説明するXMLと、データを取得してCSSスタイルシートを適用するビューを提供するプレゼンターと考えることができます。具体的には、発表者が電話をかけるIRoadMapView.SetRoadCondition(RoadCondition.Slippery)
と、ビューが道路を赤色で表示します。
クリックされたノードのデータはどうですか?
5. ツリーノードをクリックしたときに、特定のノードをプレゼンターに渡し、そこからプレゼンターが必要なデータを算出し、モデルにそのデータを要求してから、ビューに戻す必要がある場合はどうすればよいですか。
できれば、ツリーをビューに表示するために必要なすべてのデータを一度に渡します。しかし、一部のデータが最初から渡すには大きすぎる場合、またはその性質が動的であり、モデルから(プレゼンターを介して)「最新のスナップショット」が必要な場合event LoadNodeDetailsEventHandler LoadNodeDetails
は、ビューインターフェイスに次のようなものを追加して、プレゼンターはそれにサブスクライブしLoadNodeDetailsEventArgs.Node
、モデルからノードの詳細を(おそらくそのIDを介して)フェッチできるため、イベントハンドラーデリゲートが戻るときにビューが表示されたノードの詳細を更新できます。ユーザーエクスペリエンスを向上させるためにデータのフェッチが遅すぎる場合は、この非同期パターンが必要になる場合があることに注意してください。