如何将用户控件(视图)中的逻辑剥离到演示者
Posted
技术标签:
【中文标题】如何将用户控件(视图)中的逻辑剥离到演示者【英文标题】:How can I strip out logic from a UserControl (View) to the Presenter 【发布时间】:2015-09-23 18:04:25 【问题描述】:这是我第一次尝试让 MVP 与 WinForms 一起工作。我确实有一个更大的项目。但是,在这里我对 WinForms MVP 示例进行了非常简单的尝试。我只有一个模型、一个表单和两个视图。演示者在 Program.cs 中连接。一切正常。但是,对于一个特定的用户控件,我似乎无法将其余的业务逻辑重构到 Presenter 中。我正在尝试制作一个易于修改为演示项目的示例。我真的不是在寻找简单的让它工作,而是我在寻找“经典”的答案,如果有这样的事情。感谢您提供的任何帮助或建议。即使是朝着正确的方向推动也会有很大的帮助。
我的 MainFormPresenter:
internal class MainFormPresenter
private readonly SimpleContext _context = new SimpleContext();
private readonly IMainFormView _mainFormView;
private readonly IPeopleListView _peopleListView;
private readonly IPersonInfoView _personInfoView;
public MainFormPresenter(IMainFormView mainFormView)
_peopleListView = mainFormView.PeopleListView;
_personInfoView = mainFormView.PersonInfoView;
_mainFormView = mainFormView;
mainFormView.Load += MainFormViewOnLoad;
mainFormView.FormClosed += MainFormViewOnFormClosed;
_peopleListView.SelectionChanged += OnSelectedNameChanged;
private void OnSelectedNameChanged(object sender, EventArgs e)
int id = _peopleListView.GetSelectedId();
Person person = _context.People.Find(id);
_personInfoView.SetFirstName(person.FirstName);
_personInfoView.SetLastName(person.LastName);
_personInfoView.SetBirthDate(person.BirthDate);
private void MainFormViewOnFormClosed(object sender, FormClosedEventArgs e)
_context.Dispose();
private void MainFormViewOnLoad(object sender, EventArgs e)
_context.People.Load();
BindingList<Person> people = _context.People.Local.ToBindingList();
_peopleListView.SetDataSource(people);
我的 PeopleListView 的代码隐藏:
public partial class PeopleListView : UserControl, IPeopleListView
private readonly BindingSource _bSource;
public PeopleListView()
_bSource = new BindingSource();
InitializeComponent();
public int GetSelectedId()
DataGridViewRow row = PeopleGridView.CurrentRow;
if (row != null)
Person person = (Person)row.DataBoundItem;
return person.PersonId;
return 0;
public void SetDataSource(BindingList<Person> people)
_bSource.DataSource = people;
_bSource.RaiseListChangedEvents = true;
PeopleGridView.AutoGenerateColumns = false;
PeopleGridView.DataSource = _bSource;
private void PeopleGridView_SelectionChanged(object sender, EventArgs e)
SelectionChanged?.Invoke(new object(), new EventArgs());
public event EventHandler SelectionChanged;
现在如何将这个逻辑提取回 Presenter? MVP 模式(根据 Pluralsight 的 - Windows Forms Best Practices)声明视图不应该关心它显示的数据。例如关注点分离。但我希望我的视图在模型更改时更新。
【问题讨论】:
【参考方案1】:这可能不是佳能,但我是这样处理的。建设性的批评仍然非常受欢迎。简单地说,只是称我为无思想的白痴或告诉我我做错了什么也是找到的。
我修改后的 Presenter:
internal class MainFormPresenter
private readonly SimpleContext _context = new SimpleContext();
private readonly IMainFormView _mainFormView;
private readonly IPeopleListView _peopleListView;
private readonly IPersonInfoView _personInfoView;
public MainFormPresenter(IMainFormView mainFormView)
_peopleListView = mainFormView.PeopleListView;
_personInfoView = mainFormView.PersonInfoView;
_mainFormView = mainFormView;
_mainFormView.Load += MainFormViewOnLoad;
_mainFormView.FormClosed += MainFormViewOnFormClosed;
_peopleListView.SelectionChanged += OnSelectedNameChanged;
private void OnSelectedNameChanged(object sender, EventArgs e)
DataGridViewRow row = _peopleListView.GetSelectedRow();
Person person = (Person) row.DataBoundItem;
_personInfoView.SetFirstName(person.FirstName);
_personInfoView.SetLastName(person.LastName);
_personInfoView.SetBirthDate(person.BirthDate);
private void MainFormViewOnFormClosed(object sender, FormClosedEventArgs e)
_context.Dispose();
private void MainFormViewOnLoad(object sender, EventArgs e)
_context.People.Load();
BindingList<Person> people = _context.People.Local.ToBindingList();
BindingSource bSource = new BindingSource
DataSource = people,
RaiseListChangedEvents = true
;
_peopleListView.SetDataSource(bSource);
我修改的用户控件(视图):
public partial class PeopleListView : UserControl, IPeopleListView
public PeopleListView()
InitializeComponent();
public DataGridViewRow GetSelectedRow()
return PeopleGridView.CurrentRow;
public void SetDataSource(BindingSource bSource)
PeopleGridView.AutoGenerateColumns = false;
PeopleGridView.DataSource = bSource;
private void PeopleGridView_SelectionChanged(object sender, EventArgs e)
SelectionChanged?.Invoke(new object(), new EventArgs());
public event EventHandler SelectionChanged;
【讨论】:
以上是关于如何将用户控件(视图)中的逻辑剥离到演示者的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin.Forms自定义用户界面控件实现一个HybridWebView(混合webview)
如何使用 UINavigationController 中的所有视图和导航控制器的导航控件检测用户活动?