利用WinForms平台实现MVP

问题描述 投票:0回答:1

我正在使用 MVP 模式在 WinForms 上创建一个应用程序。我为每个表单都有一个单独的项目,视图的界面位于单独的项目中。演讲者也有自己独立的项目。我有两个问题:

  1. 如何使用 MVP 正确构建 Winforms 应用程序

  2. 如果需要,如何通过演示者向表单添加控件(我有一个主表单,上面有一个注册按钮,单击此按钮将打开注册表单作为我使用 UserControl 的注册表单)。

我在winforms类库中创建了一个presenter,使用Action delegate作为事件参数,但我认为这不是正确的做法,有更好的解决方案

c# winforms mvp
1个回答
0
投票

您的 Form 类是 Presenter:它位于视图(= 与操作员交互)和模型之间。

我假设您知道如何使用 Visual Studio Designer 来创建和设计表单。

您的 Form 类有(引用)您的模型的实例。

IMyModel Model {get => ...}

从操作员(视图)到模型的输入

每当操作员按下按钮、选择项目等时,就会生成一个事件。使用 Visual Studio 设计器为此生成事件处理程序。该事件处理程序是在您的 Form 类(Presenter)中创建的。

例如,操作员在文本框中键入产品 ID,然后按“获取产品信息”按钮。在您的表格课程中:

void OnButtonGetProductInformation_Clicked(object sender, ...)
{
}

void DisplayRequestedProduct()
{
    string textProductId = this.textBoxProductId.Text;
    int productId = Int32.Parse(textProductId)
    this.DisplayProduct(productId);
}

void DisplayProduct(int productId)
{
    IProduct product = this.Model.GetProduct(productId)
    // fetches the product with productId from the Database

    this.DisplayProduct(product);
}


Product DisplayedProduct {get; set;}

void DisplayProduct(Product product)
{
    // show some product data in labels
    this.labelProductId.Text = product.Id;
    this.labelProductName.Text = product.Name;
    this.labelProductDescription.Text = product.Description;
    this.labelProductPrice.Text = product.Price.ToString(...);
    this.labelProductStock.Text = product.Stock.ToString(...);

    this.DisplayedProduct = product;
}

我将操作分成小方法,因此这些方法更容易进行单元测试,可以重用,并且更改不会影响其他方法。例如,如果您想在编辑框或表格中显示获取的产品,其他过程不会改变。

顺便说一下,为了简单起见,我没有检查输入的productId。当然你应该检查输入是否是正确的整数,以及输入是否是现有产品的productId。

从模型到视图的输出

某些模型的数据会发生变化。更改应在视图中自动更新。例如,如果产品已售出,则应更新库存,如果产品已售完,则显示的产品应显示为红色。

只要其中一个产品发生变化,IMyModel 就应该引发一个事件。您应该在您的表单中订阅此活动:

void SubScribeEventProductChanges()
{
    this.Model.ProductChanged += this.OnProductChanged;
}

void OnProductChanged(object sender, ProductChangedEventData e)
{
    // is my displayed Product changed?
    if (e.ChangedProduct.Id == this.DisplayedProduct.Id
    {
        // The name, price, etc of the Product can be changed 
        this.DisplayProduct(e.ChangedProduct);  // slightly changed version
    }
    // else: not my product, nothing to do
}

void DisplayProduct(Product product)
{
    Color productTextColor = this.GetProductTextColor(product);
    this.SetProductDisplayColor(productTextColor);

    // as in earlier method:
    this.labelProductId.Text = product.Id;
    this.labelProductName.Text = product.Name;
    ...
}

Color GetProductTextColor(Product product)
{
    return (product.Stock == 0) ? Color.Red : Color.Black;
}

void SetProductDisplayColor(Color productDisplayColor)
{
    this.labelProductId.ForeColor = productDisplayColor;
    this.labelProductName.ForeColor = productDisplayColor;
    ... etc.
}

因为我制作的小程序只有一项小任务,所以我必须对现有程序进行的更改很小。

结论

实现 MVP 或 MVVM:

只要其他人需要知道的值发生变化,模型就应该引发事件。

表单类必须有一个返回模型对象接口的属性。来自操作员的输入由表单类使用事件处理。如果这意味着必须通知模型,则从模型接口形成类方法。

表单类订阅它需要的模型事件。如果引发事件,模型类将检查视图是否必须更新,并采取相应的行动。

© www.soinside.com 2019 - 2024. All rights reserved.