ドロップダウン用の「ウィジェット」インターフェースを作成することもできます。TextBox ウィジェットの実用的なコードの簡単な例を示して、アイデアを理解してもらいます。
public interface ITextWidget
{
event EventHandler TextChanged;
string Text { get; set; }
}
public abstract class TextWidget<T> : ITextWidget
{
protected T _wrappedWidget { get; set; }
public event EventHandler TextChanged;
protected void InvokeTextChanged(object sender, EventArgs e)
{
var textChanged = TextChanged;
if (textChanged != null) textChanged(this, e);
}
public abstract string Text { get; set; }
}
これまでのところ、すべてがテクノロジーに依存していないことに注意してください。ここで、Win Forms TextBox の実装を示します。
public class TextBoxWidget : TextWidget<TextBox>
{
public TextBoxWidget(TextBox textBox)
{
textBox.TextChanged += InvokeTextChanged;
_wrappedWidget = textBox;
}
public override string Text
{
get { return _wrappedWidget.Text; }
set { _wrappedWidget.Text = value; }
}
}
これは Form 自体でインスタンス化され、MVP に戻ると IViewWhatever になります。
public partial class ProjectPickerForm : Form, IProjectPickerView
{
private IProjectPickerPresenter _presenter;
public void InitializePresenter(IProjectPickerPresenter presenter) {
_presenter = presenter;
_presenter.InitializeWidgets(
...
new TextBoxWidget(txtDescription));
}
...
}
そしてプレゼンターで:
public class ProjectPickerPresenter : IProjectPickerPresenter
{
...
public void InitializeWidgets(ITextWidget descriptionFilter) {
Check.RequireNotNull<ITextWidget>(descriptionFilter, "descriptionFilter");
DescriptionFilter = descriptionFilter;
DescriptionFilter.Text = string.Empty;
DescriptionFilter.TextChanged += OnDescriptionTextChanged;
}
...
public void OnDescriptionTextChanged(object sender, EventArgs e) {
FilterService.DescriptionFilterValue = DescriptionFilter.Text;
}
アイデアを思いつくと、ほとんどの作業はかなり機械的なものになるため、セットアップするよりも見た目が悪くなります。きれいな部分は、プレゼンターが、実際に実装されたウィジェットが何であるかを知らず、気にせずに、ウィジェットで必要な情報を取得 (および設定) できることです。また、同じタイプ (ここでは Win フォーム) の他のウィジェット (それらのライブラリを構築することになります) や、必要に応じて他の UI テクノロジ (インターフェイス/基本クラスを取得したら、別のテクノロジでの実装は些細なことです)。インターフェイスがあるため、モック オブジェクトでのテストも簡単です。そして、あなたの UI は、UI 関連のタスク以外は驚くほど無知です。欠点は、ウィジェットごとのクラスの束と、それに慣れるための少しの学習曲線です。
ドロップダウンには、SelectedIndexChanged タイプのイベントが必要なだけかもしれません。これは、この例の TextChanged イベントの代わりになります。