Re[19]: Model-View-Controller в .Net
От: Greg Zubankov СССР  
Дата: 06.06.07 07:19
Оценка:
Здравствуйте, IB, Вы писали:

IB>Так задавайте конструктивные вопросы.


Возникли вопросы по применению схемы MVP к созданию пользовательских элементов управления.
Для примера можно взять обыкновенную кнопку. Если возможно, прокомментируйте мои следующие рассуждения и мысли.

Модель
-------
Поскольку кнопка может находиться в нескольких состояних State (normal, pressed, hottracked, disabled) необходимо где-то его сохранить. Пусть это будет модель.
Для возможности создания windowless контрола необходима также информация о местоположении кнопки Rect. Снова в модель.
С данными вроде разобрались.
  class ButtonModel
  ...
    // get
    Rect GetRect() const;
    State GetState() const;
    // set
    bool SetRect(Rect const&); // bool для уведомления о результете изменения  успех/неудача
    bool SetState(State);



View
-------
В случае с кнопкой интерфейс представления будет состоять из функций для отображения кнопки на экране, запроса на перерисовку кнопки и событий оповещающих Presenter о движении мыши и нажатиях на кнопки мыши (клавиатурные команды для простоты рассматривать не будем).
Получается так:
  class ButtonView
    ...
    // draw
    virtual void DrawButton(Rect const&, State) = 0;
    virtual void Invalidate(Rect const&) = 0;
    // ??? нужны ли
    virtual void CaptureMouse() = 0;
    virtual void ReleaseMouse() = 0;
    virtual bool IsMouseCaptured() = 0;

    DrawEvent OnDrawEvent;
    MouseMoveEvent OnMouseMoveEvent;
    LButtonDownEvent OnLButtonDownEvent;
    LButtonUpEvent OnLButtonUpEvent;

Тут у меня появляется небольшое недопонимание. Помимо вышеперечисленных функций Презентеру (поскольку он управляет логикой контрола) может понадобиться CaptureMouse и ReleaseMouse для корректного перехода из состояния в сотояние. К примеру юзер нажал на кнопку, но отпускать не спешит. Информация о движении мыши должна поступать в контрол даже если юзер при нажатой кнопке уведет мышь за пределы родительского окна. Достичь этого можно например захватив мышь. Выходит Презентер должен знать об особенностях конкретного представления, оконной библиотеки?

Presenter
---------
  class ButtonPresenter
  ...
    ButtonPresenter(Model*, View*);

    void OnDraw();
    void OnMouseMove(Point const&);
    bool OnLButtonDown(Point const&); // bool для уведомления о том, что сообщение обработано
    bool OnLButtonUp(Point const&);

// пример реализации одной из функций
bool ButtonPresenter::OnLButtonDown(Point const& pt)
{
  if(model->GetRect().IsPointInRect(pt))
  {
    view_->CaptureMouse();
    if(model_->SetState(State::Pressed))
    {
        view->Invalidate(model_.GetRect());
    }
    return true;
  }
  return false;
}


Реализации функций View у конкретного наследника тривиальна, приводить смысла не имеет. Здесь интересно другое. Если владелец кнопки захочет изменить ее местоположение или (пусть даже так) состояние, функциями какого класса он будет пользоваться? Не совсем правильно поставил вопрос. Конечно подобные функции есть только у модели. Но ведь у нее нет уведомлений представлению или презентеру об изменении. Что необходимо сделать? Добавить SetRect, SetState к Презентеру, Реализации вида или уведомления модели? Я немного запутался. Может в данном конкретном случае модель не нужна вовсе?

Также много вопросов возникает по взаимодействию триад MVP. Можете посоветовать конкретные примеры, в которых не сложно будет разобраться? Ну или сложно

PS. Большинство примеров что видел я, (например здесь) использую активную модель, более того именно модель (в одном из примеров — игра puzzle) является инициатором старта новых диалогов.

PPS. Прощу прощения за сумбурность изложения мыслей
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.