Как правильно реализовать MVC с помощью C # .NET в приложениях Windows Forms - PullRequest
8 голосов
/ 15 июля 2011

Я искал во всем Интернете примеры реализаций установки MVC в .NET.Я нашел много примеров, но все они, кажется, отличаются в определенных аспектах.У меня есть книга по шаблонам проектирования, в которой описано, что MVC был создан на Smalltalk, поэтому я прочитал несколько человек, обсуждающих его реализацию на этом языке.Ниже приведен пример проекта, который я написал с использованием того, что я собрал, было правильной реализацией, но меня смутили некоторые детали.

Одна проблема, с которой я столкнулся, - это правильный порядок построения объектов.Вот импл в моем Program.cs

Model mdl = new Model();
Controller ctrl = new Controller(mdl);
Application.Run(new Form1(ctrl, mdl));

Вид: Сразу же у меня есть пара вопросов, в которых я не уверен.Во-первых, если представление должно считывать только данные из Модели для обновления, но содержит ссылку на него, что мешает мне делать вызовы, которые контроллер делает с моделью из представления?Должен ли программист просто игнорировать тот факт, что они подвергаются функциям-членам моделей?Еще одна мысль, которая у меня была, - возможно, это событие, информирующее представление об обновлении модели, - отправка какого-либо объекта состояния для представления, с помощью которого можно обновить само представление.

public interface IView
{
    double TopSpeed { get; }
    double ZeroTo60 { get; }

    int VehicleID { get; }
    string VehicleName { get; }
}

/// <summary>
/// Assume the form has the following controls
/// A button with a click event OnSaveClicked
/// A combobox with a selected index changed event OnSelectedIndexChanged
/// A textbox that displays the vehicles top speed named mTextTopSpeed
/// A textbox that displays the vehicles zero to 60 time named mTextZeroTo60
/// </summary>

public partial class Form1 : Form, IView
{
    private IController mController;
    private IModel mModel;

    public Form1(IController controller, IModel model)
    {
        InitializeComponent();

        mController = controller;
        mController.SetListener(this);
        mModel = model;
        mModel.ModelChanged += new ModelUpdated(mModel_ModelChanged);
    }

    void mModel_ModelChanged(object sender, EventArgs e)
    {
        mTextTopSpeed.Text = mModel.TopSpeed.ToString();
        mTextZeroTo60.Text = mModel.ZeroTo60.ToString();
    }

    public double TopSpeed { get { return Double.Parse(mTextTopSpeed.Text); } }

    public double ZeroTo60 { get { return Double.Parse(mTextZeroTo60.Text); } }

    public int VehicleID { get { return (int)mComboVehicles.SelectedValue; } }

    public string VehicleName { get { return mComboVehicles.SelectedText; } }

    #region Form Events

    private void OnFormLoad(object sender, EventArgs e)
    {
        mComboVehicles.ValueMember = "Key";
        mComboVehicles.DisplayMember = "Value";
        mComboVehicles.DataSource = new BindingSource(mModel.VehicleList, null);
    }

    private void OnSelectedIndexChanged(object sender, EventArgs e)
    {
        mController.OnSelectedVehicleChanged();
    }

    private void OnSaveClicked(object sender, EventArgs e)
    {
        mController.OnUpdateVehicle();
    }

    #endregion
}

Контроллер: Моя единственная реальная проблема сспособ, которым я реализовал контроллер, состоит в том, что мне кажется немного странным, что возможно создать контроллер без определенного назначения ему.Я мог бы полностью игнорировать представление, но это означало бы, что я передам параметры функциям контроллера для обновления модели, которая, по-видимому, полностью упускает точку.

public interface IController
{
    void OnUpdateVehicle();
    void OnSelectedVehicleChanged();
    void SetListener(IView view);
}

class Controller : IController
{
    private IModel mModel;
    private IView mView = null;

    public Controller(IModel model)
    {
        mModel = model;
    }

    public void OnUpdateVehicle()
    {
        if(mView == null)
            return;

        mModel.UpdateVehicle(mView.VehicleID, mView.TopSpeed, mView.ZeroTo60);
    }

    public void SetListener(IView view)
    {
        mView = view;
    }

    public void OnSelectedVehicleChanged()
    {
        if (mView == null)
            return;
        mModel.SelectVehicle(mView.VehicleID);
    }
}

Модель: В моей форме у меня есть комбинированный списокэто список транспортных средств, приведенных в моей псевдо-базе данных.Мне кажется, что моя форма должна реализовывать несколько видов / моделей из-за этого.Представление, относящееся к списку возможных транспортных средств с соответствующим контроллером / моделью, и представление для отображения информации о выбранном транспортном средстве с его собственным контроллером / моделью.

public delegate void ModelUpdated(object sender, EventArgs e);

public interface IModel
{
    event ModelUpdated ModelChanged;

    void UpdateVehicle(int id, double topSpeed, double zeroTo60);
    void SelectVehicle(int id);

    double TopSpeed { get; }
    double ZeroTo60 { get; }
    IDictionary<int, string> VehicleList { get; }
}

// class for the sake of a pseudo database object
class Vehicle
{
    public int ID { get; set; }
    public string Name { get; set; }
    public double TopSpeed { get; set; }
    public double ZeroTo60 { get; set; }

    public Vehicle(int id, string name, double topSpeed, double zeroTo60)
    {
        ID = id;
        Name = name;
        TopSpeed = topSpeed;
        ZeroTo60 = zeroTo60;
    }
}


class Model : IModel
{
    private List<Vehicle> mVehicles = new List<Vehicle>()
    {
        new Vehicle(1, "Civic", 120.0, 5.0),
        new Vehicle(2, "Batmobile", 9000.0, 1.0),
        new Vehicle(3, "Tricycle", 5.0, 0.0)
    };

    private Vehicle mCurrentVehicle;

    public Model()
    {
        mCurrentVehicle = mVehicles[0];
    }

    public event ModelUpdated ModelChanged;

    public void OnModelChanged()
    {
        if (ModelChanged != null)
        {
            ModelChanged(this, new EventArgs());
        }
    }

    public double TopSpeed { get { return mCurrentVehicle.TopSpeed; } }

    public double ZeroTo60 { get { return mCurrentVehicle.ZeroTo60; } }

    public IDictionary<int, string> VehicleList
    {
        get 
        {
            Dictionary<int, string> vDict = new Dictionary<int, string>();
            foreach (Vehicle v in mVehicles)
            {
                vDict.Add(v.ID, v.Name);
            }

            return vDict as IDictionary<int, string>;
        }
    }

    #region Pseudo Database Calls

    public void SelectVehicle(int id)
    {
        foreach (Vehicle v in mVehicles)
        {
            if (v.ID == id)
            {
                mCurrentVehicle = v;
                OnModelChanged(); // send notification to registered views
                break;
            }
        }
    }

    public void UpdateVehicle(int id, double topSpeed, double zeroTo60)
    {
        foreach (Vehicle v in mVehicles)
        {
            if (v.ID == id)
            {
                mCurrentVehicle.TopSpeed = topSpeed;
                mCurrentVehicle.ZeroTo60 = zeroTo60;
                OnModelChanged(); // send notification to registered views
                break;
            }
        }
    }

    #endregion
}

В заключение настоящего тл; dr, Iугадайте, что я ищу, это какое-то руководство о том, представляет ли то, что я здесь делаю, настоящую реализацию MVC и, возможно, кто-то сможет пролить свет на вышеупомянутые проблемы.Любой совет будет принята с благодарностью.

1 Ответ

4 голосов
/ 15 июля 2011

Мы будем, это зависит от того, что вы хотите сделать.В настоящее время у вас есть реализация Supervising Controller.Если вы хотите удалить модель из вида (и любой привязки данных), вы можете вместо этого реализовать шаблон пассивного вида.См. эту статью для получения дополнительных отличий.

Пассивное представление и Контролирующий контроллер http://i.msdn.microsoft.com/dynimg/IC281772.png

И Мартин Фаулер - король ( Архитектура графического интерфейса ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...