【问题标题】:C# Win Forms. Passing valuesC# Winforms。传递值
【发布时间】:2017-02-22 08:23:16
【问题描述】:

我有多个相互交互的winforms。一个表单允许用户输入一组属性,然后验证它们并单击按钮移动到下一个表单。用户可以随时选择退出并转到之前的表单。

我有一个记录基本属性值的业务对象类。

现在,我最初使用简单、朴素的参数在表单之间交换值。例如,假设 Form1 和 Form2。在按钮上单击“下一步”Form1 被隐藏并显示 Form2:-

   // event of button click "Next" on Form1.cs //
    private void btnNext_Click(object sender, EventArgs e)
    {
        Form2 form2 = new Form2 (myTxtBoxValue.Text);
        form2.Show();
        this.Hide();
    }


    // constructor in Form2.cs //
    public Form2(string myTxtBoxValue)
    {
        InitializeComponent();
        TransactionBO trans = new TransactionBO();
        trans.myValue = myTxtBoxValue;  // <-- this gets the value accurately. 
    }

    // my Business Object class is called TransactionBO.cs //
    class TransactionBO
    {
       public string myValue {get;set;}
    }

但是,有人建议我这样做的更好方法是使用单例。原因是“最好不要将 form2 绑定到 form1,创建依赖项可能会降低未来的灵活性/可扩展性”。

有人可以解释一下我的原因吗?以及如何使用单例(我知道单例的基本原理是什么,我必须创建一个单独的单例类还是可以使用我的 TransactionBO.cs 类在表单之间传递值)?

【问题讨论】:

  • 你描述的看起来像向导控制。你在实施那种东西吗?
  • 在一个表单中使用多个面板不是更好吗?
  • 您可以使用Wizard-like 控件。您可以拥有在向导的不同页面之间使用的单个模型对象。每个向导页面中托管的控件(或用户控件)实际上是您希望在每个步骤中用于模型的不同视图。
  • 你的同事落后了大约 10 年。单例模式是 now considered an anti-pattern 并且已经被废弃,部分原因是它给单元测试带来了巨大的问题。
  • @OP,this answer 中描述了许多技术。你的并不糟糕;它不会是我的第一选择,但如果它已经基本完成,我不会费心重写它。

标签: c# forms winforms


【解决方案1】:

让我们解决您的同事对依赖性的担忧。

为了水平集,我们来看一些拓扑图。想象一下这些是依赖图。

根据细节,您当前的设计将有一个依赖关系图,它可以是一条线、一个网格,或者是“完全连接的”。所有这些图表都具有这样的特性,即图表中任何单个节点的代码更改都需要检查,并且可能需要在许多其他点进行更改,并且在某些情况下所有都必须查看。这很糟糕。

我们更喜欢更简单的图表。例如,一棵树要简单得多。但最好的是明星。在星图中,您只有成对的依赖关系;对任何一个节点的更改最多需要检查一个其他节点。这意味着有更好的隔离性和对修改的弹性。

那么,在您的案例中,我们如何获得星图?以下是我的做法。

  1. 定义一个代表整个工作流的新类。例如,如果它是注册服务的工作流,您可以将其称为EnrollmentWorkflow。在本例中,我将其命名为 Workflow

  2. Workflow 一系列字段和公共属性,代表您需要从用户那里收集的每个数据项。

  3. 在启动多步用户界面的代码中,创建一个新的Workflow 实例并将其传递给第一个表单的构造函数。

  4. 在用户完成表单时触发的事件处理程序中,添加代码以将表单的所有字段复制到Workflow 的属性中。然后实例化下一个表单,在构造函数中传递相同的 Workflow 实例。

  5. 在下一个表单中,您可以从 Workflow 对象中读取所需的所有值。

  6. 像这样继续直到最后一步完成,此时您会将工作流传递给业务逻辑层进行处理。

  7. 如果您愿意,您可以将帮助方法添加到工作流中,用于数据查找、字段验证等操作,以便将它们全部包含在一个位置。

  8. 如果用户需要保存进度并稍后恢复,将 Workflow 持久化为序列化对象是一件非常简单的事情,只需少量工作。

最后,Workflow 对象将成为星形图的中心,表单将成为周边的节点。通过这种方式,您最终得到了一个漂亮、简单的依赖关系图,以及一个易于修改的良好设计。

【讨论】:

  • 谢谢!这是我最初的想法。但我觉得我不需要 2 个单独的课程。 TransactionBO 具有完成我的交易所需的所有属性和方法。我假设如果我有一个从 Form1 传递到 Form2 的 TransactionBO obj,然后最终验证并处理存储在 TransactionBO 中的所有用户输入,那么我的工作流将被维护并存储在一个对象中。你的想法?
  • 是的,对于初学者来说应该没问题(这不像我们在这里建造阿波罗 11 号)。也许在 TransactionBO 上定义一个只包含您需要的字段的接口,然后使用它来代替……这样,如果您以后想添加一个单独的 Workflow 类,重构会更容易。
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 2023-03-09
  • 2022-09-29
相关资源
最近更新 更多