我希望你们可以帮助我,因为我找不到任何有用的东西,有助于理解我的问题:
我试图在我的C#WinForms应用程序上实现一种被动的MVP方法,该方法具有列表视图和相应的详细视图。
到目前为止,我已经获得了以下结构(伪代码):
ListPresenter(new Repository(), new ListView(), new DetailPresenter(new DetailView());
实现:
public class UserDetailPresenter : IPresenter<IUserDetailView>
{
private IDetailView _view;
public UserDetailPresenter(IDetailView detailView)
{
_view = detailView;
}
public void Show(IUser user)
{
InitializeView(user);
_view.Show();
}
}
public class UserListPresenter
{
//private members (_userRepo, _listView, _detailPresenter)
public UserListView(IUserRepository userRepo, IListView listView, IDetailPresenter detailPresenter)
{
//wire up private members..
_listView.EditCommandFired += this.ShowEditForm;
}
private void OnListViewEditCommandFired(object sender, EventArgs args)
{
_detailPresenter.LoadUser(_listView.SelectedUser);
_detailPresenter.Show(); //modal
}
}
public class UserListForm : Form, IUserListView
{
public event EventHandler EditCommandFired;
public IUser SelectedUser { get { return gridView.FocusedRowHandle as IUser; } }
public void LoadUsers(List<IUser> users)
{
gridView.DataSource = users;
}
// other UI stuff
}
我的问题是:我只能显示一次编辑表单。一旦我尝试再次打开它,我的View(表单)就被处理掉了(System.ObjectDisposedException)。
我该如何解决?我这里有错误的做法吗?我是否要取消表单的关闭并隐藏它并信任垃圾收集器在DetailPresenter
处置后收集它?每次Edit
事件被触发时,我是否创建(new()up)新的演示者?然后,我将不得不介绍某种工厂,因为我不知何故失去依赖注入。如果有人能够指出这种情况下的最佳做法会是什么样子以及我在这里做错了什么,我会说不出来。
答案 0 :(得分:0)
前一段时间我正在做Winforms MVP所以不确定我是否可以提供帮助,但案例如下。 在我的方法中,视图拥有演示者,伪代码:
MyForm form = new MyForm(new PresenterX);
form.Show(); //or showdialog
在这种情况下,实例在关闭后仍然存在。
在您的情况下,由于演示者拥有视图,因此一旦不使用演示者,GC可能会处理演示者和包含的视图。 或者即使演示者仍在使用中,因为视图是私有的,GC可能会在关闭后收集它。
尝试在发布模式下进行调试,看看封闭表单实例会发生什么。
编辑:
其他想法是: 首先创建视图实例,然后传递给演示者
所以可能会失败的方法(我不会看到完整的代码所以猜测)
UserDetailPresenter p = new UserDetailPresenter(new YourView());
尝试
YourForm view = new YourForm(); //as global variable, view should be reusable anyway
代码中的某处
UserDetailPresenter p = new UserDetailPresenter(view);
p.Show(userInstance);
答案 1 :(得分:0)
您正在使用DetailPresenter
的一个实例来显示不同对象的详细信息。因此,在当前实现中,每次要显示DetailPresenter
时,都必须初始化视图。这可能是这样做的一种方式,每次ListPresenter
要求new instance
显示DetailsView
时,DetailPresenter
都可以注入public class UserDetailPresenter : IPresenter<IUserDetailView>
{
private IDetailView _view;
public UserDetailPresenter()
{
}
public void Show(IUser user, IDetailView detailView)
{
_view = detailView;
InitializeView(user);
_view.Show();
}
}
ViewFactory
。
private IDetailViewFactory _detailViewFactory;
public UserDetailPresenter(IDetailViewFactory detailViewFactory)
{
_detailViewFactory = detailViewFactory;
}
public void Show(IUser user )
{
_view = _detailViewFactory.Resolve();//Some method to get a new view
InitializeView(user);
_view.Show();
}
或者另一种更干净的方式可能是某种passive view
来获取视图的新实例,然后再显示它。
ListPresenter
但是如果你想稍微改变一下,那就更private void OnListViewEditCommandFired(object sender, EventArgs args)
{
_listView.Show(_listView.SelectedUser);//tells view to show another view
}
了。
在ListView
:
public ListView()
{
new ListPresenter(this); // initializes presenter
}
public void Show(IUser user)
{
new DetailsView(user); // creates a new view
}
在DetailsView
:
public DetailsView(IUser user)
{
new DetailsPresenter(this, user); //creates presenter
}
在public class UserDetailPresenter : IPresenter<IUserDetailView>
{
private IDetailView _view;
public UserDetailPresenter(IDetailView detailView, IUser user)
{
_view = detailView;
LoadUser(user);
_view.SomeProperty = _userData;//to populate view with data
_view.Show(); // tells the view to show data
}
}
:
{{1}}
最后:
{{1}}