清单+细节 - 最佳方法?

时间:2013-12-19 15:05:55

标签: c# .net winforms mvp detailview

我希望你们可以帮助我,因为我找不到任何有用的东西,有助于理解我的问题:

我试图在我的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)新的演示者?然后,我将不得不介绍某种工厂,因为我不知何故失去依赖注入。如果有人能够指出这种情况下的最佳做法会是什么样子以及我在这里做错了什么,我会说不出来。

2 个答案:

答案 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}}