Model view controller 这段代码的MVC版本是什么?

Model view controller 这段代码的MVC版本是什么?,model-view-controller,language-agnostic,design-patterns,Model View Controller,Language Agnostic,Design Patterns,我正试图将我的头脑集中在如何对代码进行企业化上:使用一个简单的例程,并将其拆分为3或4个类中的5或6个方法 我很快想出了三个简单的代码示例,说明了我目前是如何编写它的。有人能把这些转换成MVC/MVP模糊版本吗 示例1:姓氏是必填项。如果未输入任何内容,则将文本框涂成红色。如果输入了内容,则将其涂成绿色: private void txtLastname_TextChanged(object sender, EventArgs e) { //Lastname mandatory.

我正试图将我的头脑集中在如何对代码进行企业化上:使用一个简单的例程,并将其拆分为3或4个类中的5或6个方法

我很快想出了三个简单的代码示例,说明了我目前是如何编写它的。有人能把这些转换成MVC/MVP模糊版本吗


示例1:姓氏是必填项。如果未输入任何内容,则将文本框涂成红色。如果输入了内容,则将其涂成绿色:

private void txtLastname_TextChanged(object sender, EventArgs e)
{
   //Lastname mandatory. 
   //Color pinkish if nothing entered. Greenish if entered.
   if (txtLastname.Text.Trim() == "")
   {
      //Lastname is required, color pinkish
      txtLastname.BackColor = ControlBad;
   }
   else
   {
      //Lastname entered, remove the coloring
      txtLastname.BackColor = ControlGood;
   }
}

示例2:名字是可选的,但是尝试获取它。我们将在“尝试获取”字段中添加蓝色色调:


例3年龄完全是可选的。如果输入了年龄,则该年龄最好有效:

private void txtAge_TextChanged(object sender, EventArgs e)
{
   //Age is optional, but if entered it better be valid
   int nAge = 0;
   if (Int32.TryParse(txtAge.Text, out nAge))
   {
      //Valid integer entered
      if (nAge < 0)
      {
         //Negative age? i don't think so
         txtAge.BackColor = ControlBad;
      }
      else
      {
         //Valid age entered, remove coloring
         txtAge.BackColor = SystemColors.Window;
      }
   }
   else
   {
      //Whatever is in there: it's *not* a valid integer,
      if (txtAge.Text == "")
      {
         //Blank is okay
         txtAge.BackColor = SystemColors.Window;
      }
      else
      {
         //Not a valid age, bad user
         txtAge.BackColor = ControlBad;
      }
   }
}
我已经把代码弄糊涂了,但它仍然是完整的。我想MVC混淆的下一步是将代码隐藏在3或4个不同的文件中

这是我不明白的下一步。哪些函数被移入哪些其他类的逻辑分隔是什么?有人能把我上面3个简单的例子翻译成成熟的MVC混淆吗



编辑:不是ASP/ASP.NET/Online。假装它在桌面、手持设备、表面、信息亭上。并假设它与语言无关。

您在代码中所做的大部分工作都属于控制器类,因为它描述了逻辑。您的视图应该只描述UI,并提供对UI组件的轻松访问。模型类应该描述您的数据模型

想法很简单:控制器做一切,但它必须了解视图和模型。例如,当视图初始化时,控制器设置所有逻辑(类似于您已经在做的事情)。当模型分配给控制器时-它将值设置到适当的UI控件中,并执行相同的操作来检索数据并返回is As模型


因此,基本上,您将数据模型类交给控制器,它进行编辑并再次以模型类的形式返回数据

如果可能的话,在经典ASP.NET中很难遵循MVC,所以我将基于MVP进行回复

在第一个示例中,您正在尝试进行验证。验证姓氏是演示者的责任。将字段显示为红色是视图的责任。因此,您的视图类如下所示:

private void Page_Load()
{
    this._presenter = new Presenter();
}

private void txtLastname_TextChanged(object sender, EventArgs e)
{
    txtLastName.BackColor = presenter.IsLastnameValid(txtLastName.Text) ?
        ControlGood : ControlBad;
}
public Presenter()
{
    public bool IsLastNameValid(string lastname)
    {
        return string.IsNullOrEmpty(lastname);
    }
}
class Controller
{
    // This is the model we are operating on
    private Model model_;

    public enum Status
    {
        Normal,
        Required,
        Good,
        Bad
    }

    public delegate void FirstNameStatusChangedDelegate(Status newStatus);
    public event FirstNameStatusChangedDelegate FirstNameStatusChangedEvent;

    public string FirstName
    {
        get { return model_.FirstName; }
        set
        {
            if (value == "")
                RaiseFirstNameStatusChanged(Status.Required);
            else if ( value.Trim() == "" )
                RaiseFirstNameStatusChanged(Status.Bad);
            else
            {
                model_.FirstName = value;
                RaiseFirstNameStatusChanged(Status.Normal);
            }
        }
    }

    private void RaiseFirstNameStatusChanged(Status newStatus)
    {
        if ( FirstNameStatusChangedEvent != null )
            FirstNameStatusChangedEvent(newStatus);
    }
}
public partial class Dinner {
    public bool IsValid {
        get { return (GetRuleViolations().Count() == 0); }
    }
        public IEnumerable<RuleViolation> GetRuleViolations() {
        yield break;
    }
     public IEnumerable<RuleViolation> GetRuleViolations() {

        if (String.IsNullOrEmpty(Title))
            yield return new RuleViolation("Title is required", "Title");

        if (String.IsNullOrEmpty(Description))
            yield return new RuleViolation("Description is required", "Description");

        if (String.IsNullOrEmpty(HostedBy))
            yield return new RuleViolation("HostedBy is required", "HostedBy");

        if (String.IsNullOrEmpty(Address))
            yield return new RuleViolation("Address is required", "Address");

        if (String.IsNullOrEmpty(Country))
            yield return new RuleViolation("Country is required", "Address");

        if (String.IsNullOrEmpty(ContactPhone))
            yield return new RuleViolation("Phone# is required", "ContactPhone");

        if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
            yield return new RuleViolation("Phone# does not match country", "ContactPhone");

        yield break;
    }
   partial void OnValidate(ChangeAction action) {
        if (!IsValid)
            throw new ApplicationException("Rule violations prevent saving");
    }
}
您的presenter类应该是这样的:

private void Page_Load()
{
    this._presenter = new Presenter();
}

private void txtLastname_TextChanged(object sender, EventArgs e)
{
    txtLastName.BackColor = presenter.IsLastnameValid(txtLastName.Text) ?
        ControlGood : ControlBad;
}
public Presenter()
{
    public bool IsLastNameValid(string lastname)
    {
        return string.IsNullOrEmpty(lastname);
    }
}
class Controller
{
    // This is the model we are operating on
    private Model model_;

    public enum Status
    {
        Normal,
        Required,
        Good,
        Bad
    }

    public delegate void FirstNameStatusChangedDelegate(Status newStatus);
    public event FirstNameStatusChangedDelegate FirstNameStatusChangedEvent;

    public string FirstName
    {
        get { return model_.FirstName; }
        set
        {
            if (value == "")
                RaiseFirstNameStatusChanged(Status.Required);
            else if ( value.Trim() == "" )
                RaiseFirstNameStatusChanged(Status.Bad);
            else
            {
                model_.FirstName = value;
                RaiseFirstNameStatusChanged(Status.Normal);
            }
        }
    }

    private void RaiseFirstNameStatusChanged(Status newStatus)
    {
        if ( FirstNameStatusChangedEvent != null )
            FirstNameStatusChangedEvent(newStatus);
    }
}
public partial class Dinner {
    public bool IsValid {
        get { return (GetRuleViolations().Count() == 0); }
    }
        public IEnumerable<RuleViolation> GetRuleViolations() {
        yield break;
    }
     public IEnumerable<RuleViolation> GetRuleViolations() {

        if (String.IsNullOrEmpty(Title))
            yield return new RuleViolation("Title is required", "Title");

        if (String.IsNullOrEmpty(Description))
            yield return new RuleViolation("Description is required", "Description");

        if (String.IsNullOrEmpty(HostedBy))
            yield return new RuleViolation("HostedBy is required", "HostedBy");

        if (String.IsNullOrEmpty(Address))
            yield return new RuleViolation("Address is required", "Address");

        if (String.IsNullOrEmpty(Country))
            yield return new RuleViolation("Country is required", "Address");

        if (String.IsNullOrEmpty(ContactPhone))
            yield return new RuleViolation("Phone# is required", "ContactPhone");

        if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
            yield return new RuleViolation("Phone# does not match country", "ContactPhone");

        yield break;
    }
   partial void OnValidate(ChangeAction action) {
        if (!IsValid)
            throw new ApplicationException("Rule violations prevent saving");
    }
}
姓是你的模特儿


请注意,我准备这些课程只是为了展示如何形成MVP结构。在现实世界中,有很多更好的验证方法。通常情况下,您会在业务中使用这种方法,而不是验证。

我在为Windows窗体实现MVC时的主要想法是,我希望对我的模型和控制器进行单元测试。为了实现这一点,我的控制器不应该知道关于使用它的视图的任何信息,因此任何应该在UI级别处理的通知都被实现为事件。在您的示例中,我的控制器如下所示:

private void Page_Load()
{
    this._presenter = new Presenter();
}

private void txtLastname_TextChanged(object sender, EventArgs e)
{
    txtLastName.BackColor = presenter.IsLastnameValid(txtLastName.Text) ?
        ControlGood : ControlBad;
}
public Presenter()
{
    public bool IsLastNameValid(string lastname)
    {
        return string.IsNullOrEmpty(lastname);
    }
}
class Controller
{
    // This is the model we are operating on
    private Model model_;

    public enum Status
    {
        Normal,
        Required,
        Good,
        Bad
    }

    public delegate void FirstNameStatusChangedDelegate(Status newStatus);
    public event FirstNameStatusChangedDelegate FirstNameStatusChangedEvent;

    public string FirstName
    {
        get { return model_.FirstName; }
        set
        {
            if (value == "")
                RaiseFirstNameStatusChanged(Status.Required);
            else if ( value.Trim() == "" )
                RaiseFirstNameStatusChanged(Status.Bad);
            else
            {
                model_.FirstName = value;
                RaiseFirstNameStatusChanged(Status.Normal);
            }
        }
    }

    private void RaiseFirstNameStatusChanged(Status newStatus)
    {
        if ( FirstNameStatusChangedEvent != null )
            FirstNameStatusChangedEvent(newStatus);
    }
}
public partial class Dinner {
    public bool IsValid {
        get { return (GetRuleViolations().Count() == 0); }
    }
        public IEnumerable<RuleViolation> GetRuleViolations() {
        yield break;
    }
     public IEnumerable<RuleViolation> GetRuleViolations() {

        if (String.IsNullOrEmpty(Title))
            yield return new RuleViolation("Title is required", "Title");

        if (String.IsNullOrEmpty(Description))
            yield return new RuleViolation("Description is required", "Description");

        if (String.IsNullOrEmpty(HostedBy))
            yield return new RuleViolation("HostedBy is required", "HostedBy");

        if (String.IsNullOrEmpty(Address))
            yield return new RuleViolation("Address is required", "Address");

        if (String.IsNullOrEmpty(Country))
            yield return new RuleViolation("Country is required", "Address");

        if (String.IsNullOrEmpty(ContactPhone))
            yield return new RuleViolation("Phone# is required", "ContactPhone");

        if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
            yield return new RuleViolation("Phone# does not match country", "ContactPhone");

        yield break;
    }
   partial void OnValidate(ChangeAction action) {
        if (!IsValid)
            throw new ApplicationException("Rule violations prevent saving");
    }
}
该视图将为
FirstNameStatusChanged
事件提供处理程序:

class View : Form
{
    private Controller controller_;
    private static readonly Dictionary<Controller.Status, Color> statusColors_ = new Dictionary<Controller.Status, Color>
    {
        {Controller.Status.Normal, SystemColors.Window},
        {Controller.Status.Required, ControlRequired},
        {Controller.Status.Good, ControlGood},
        {Controller.Status.Bad, ControlRed}
    };

    public View(Controller controller)
    {
        InitializeComponent();
        controller_ = controller;

        contoller_.FirstNameStatusChangedEvent += OnFirstNameStatusChanged;
    }

    private void txtFirstname_TextChanged(object sender, EventArgs e)
    { controller_.FirstName = txtFirstName.Text; }

    private void OnFirstNameStatusChanged(Controller.Status newStatus)
    { txtFirstName.BackColor = statusColors_[newStatus]; }
}
类视图:表单
{
专用控制器;
私有静态只读字典statusColors\uux=新字典
{
{Controller.Status.Normal,SystemColors.Window},
{Controller.Status.Required,ControlRequired},
{Controller.Status.Good,ControlGood},
{Controller.Status.Bad,ControlRed}
};
公共视图(控制器)
{
初始化组件();
控制器=控制器;
contoller_u2;.FirstNameStatusChangedEvent+=OnFirstNameStatusChanged;
}
私有void txtFirstname_TextChanged(对象发送方,事件参数e)
{controller_u.FirstName=txtFirstName.Text;}
私有void OnFirstNameStatusChanged(Controller.Status newStatus)
{txtFirstName.BackColor=statusColors_u[newStatus];}
}

MVC/MVP模式的目的不是混淆,而是。混淆是指
(隐藏)通信中的预期含义,使通信变得混乱、故意模棱两可,并且更难解释。模式的使用是为了使代码更清晰,更易于理解。我建议你从阅读和上的维基百科条目开始

这两种模式都是对代码进行结构化的方法,以便将应用程序分解为具有明确定义的交互边界的元素,以实现特定目的。在应用程序的各个类中,没有专门针对业务关注点、输入/输出处理和表示的代码,而是在各个体系结构组件中分离和隔离这些关注点。这些体系结构元素通过交互边界(接口)彼此隔离,使它们彼此更加独立,更易于修改,而不会影响整个应用程序

伊恩

如果希望立即验证控件,则需要使用javascript或jQuery。对于经典的ASP.NET也是如此。由于您使用的是代码隐藏方法,因此我假设您的验证将等待回发

以下示例来自NerdDinner项目。NerdDinner是一个开源项目,它是ASP.NET MVC体系结构的一个示例。作者们慷慨地提供了一个教程,可在

在ASP.NET MVC中提交表单时,表单作为FormCollection对象进入相应的控制器:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
    Dinner dinner = dinnerRepository.GetDinner(id);

    try
    {
        UpdateModel(dinner);
        dinnerRepository.Save();
    }
    catch
    {
        ModelState.AddModelErrors(dinner.GetRuleViolations())
    }
    return RedirectToAction("Details", new { id = dinner.DinnerID });
}
UpdateModel接受表单值并尝试将它们填充到晚餐对象中。晚餐对象如下所示:

private void Page_Load()
{
    this._presenter = new Presenter();
}

private void txtLastname_TextChanged(object sender, EventArgs e)
{
    txtLastName.BackColor = presenter.IsLastnameValid(txtLastName.Text) ?
        ControlGood : ControlBad;
}
public Presenter()
{
    public bool IsLastNameValid(string lastname)
    {
        return string.IsNullOrEmpty(lastname);
    }
}
class Controller
{
    // This is the model we are operating on
    private Model model_;

    public enum Status
    {
        Normal,
        Required,
        Good,
        Bad
    }

    public delegate void FirstNameStatusChangedDelegate(Status newStatus);
    public event FirstNameStatusChangedDelegate FirstNameStatusChangedEvent;

    public string FirstName
    {
        get { return model_.FirstName; }
        set
        {
            if (value == "")
                RaiseFirstNameStatusChanged(Status.Required);
            else if ( value.Trim() == "" )
                RaiseFirstNameStatusChanged(Status.Bad);
            else
            {
                model_.FirstName = value;
                RaiseFirstNameStatusChanged(Status.Normal);
            }
        }
    }

    private void RaiseFirstNameStatusChanged(Status newStatus)
    {
        if ( FirstNameStatusChangedEvent != null )
            FirstNameStatusChangedEvent(newStatus);
    }
}
public partial class Dinner {
    public bool IsValid {
        get { return (GetRuleViolations().Count() == 0); }
    }
        public IEnumerable<RuleViolation> GetRuleViolations() {
        yield break;
    }
     public IEnumerable<RuleViolation> GetRuleViolations() {

        if (String.IsNullOrEmpty(Title))
            yield return new RuleViolation("Title is required", "Title");

        if (String.IsNullOrEmpty(Description))
            yield return new RuleViolation("Description is required", "Description");

        if (String.IsNullOrEmpty(HostedBy))
            yield return new RuleViolation("HostedBy is required", "HostedBy");

        if (String.IsNullOrEmpty(Address))
            yield return new RuleViolation("Address is required", "Address");

        if (String.IsNullOrEmpty(Country))
            yield return new RuleViolation("Country is required", "Address");

        if (String.IsNullOrEmpty(ContactPhone))
            yield return new RuleViolation("Phone# is required", "ContactPhone");

        if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
            yield return new RuleViolation("Phone# does not match country", "ContactPhone");

        yield break;
    }
   partial void OnValidate(ChangeAction action) {
        if (!IsValid)
            throw new ApplicationException("Rule violations prevent saving");
    }
}
公共部分课堂晚餐{
公共布尔是有效的{
获取{return(GetRuleViolations().Count()==0);}
}
公共IEnumerable GetRuleViolations(){
屈服断裂;
}
公共IEnumerable GetRuleViolations(){
if(String.IsNullOrEmpty(Title))
收益-收益-新规则违反