2013-12-19 2 views
3

Я надеюсь, что вы, ребята, можете помочь мне, как я не могу найти что-нибудь полезное, что помогает с пониманием моей проблемы:Список + Детали - лучший подход?

Я пытаюсь реализовать пассивный подход MVP в моем приложении # WinForms C, который имеет представление списка и соответствующие подробные представления.

До сих пор я получил следующую структуру (псевдо-код):

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 
} 

Моей проблемы: я могу только показать форму редактирования сразу. Как только я попытаюсь открыть его во второй раз, мой вид (форма) будет удален (System.ObjectDisposedException).

Как это исправить? Есть ли у меня неправильный подход? Отменить ли я форму закрытия и просто скрыть ее и доверять сборщику мусора, чтобы собрать ее после удаления DetailPresenter? Я создаю (новый() вверх) новый ведущий каждый раз при запуске события Edit? Тогда я должен был бы ввести какой-то завод, поскольку я как-то теряю инъекцию зависимости. Я бы уклонился, если бы кто-нибудь мог указать, как будет выглядеть лучшая практика в этом случае и что я могу делать неправильно здесь.

+0

просьба предоставить больше сотрудничества де-то мы могли бы скопировать пасту в наш VS и выполнить, чтобы увидеть, что происходит точно. –

+0

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

0

Я делал Winforms MVP некоторое время назад, поэтому не уверен, могу ли я помочь, но случай мой будет следующим. В моем подходе, вид был владеющим выступающим, псевдокод:

MyForm form = new MyForm(new PresenterX); 
form.Show(); //or showdialog 

В этом случае, например все еще там после закрытия.

В вашем случае, поскольку ведущий владеет представлением, возможно, что когда ведущий не используется, GC располагает презентатором и содержит вид. Или даже если ведущий все еще используется, так как просмотр является закрытым GC, он может собирать его после закрытия.

Попробуйте отладить в режиме деблокирования и посмотрите, что происходит с экземпляром закрытой формы.

EDIT:

Другая идея заключается в том: Создать экземпляр зрения первой, а затем перейти к Presenter

Так подход, который может потерпеть неудачу (я не»видеть полный код, угадывание)

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); 
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 
    } 
}