在.NET表单中组织UI代码

在.NET表单中组织UI代码,.net,winforms,code-organization,.net,Winforms,Code Organization,我是一个自学编程的人,没有接受过任何正式的.NET编程培训 不久前,为了开发控制传感器的GUI程序,我启动了C#,该项目已经蓬勃发展。我只是想知道如何最好地在表单中组织代码,尤其是UI代码 我的表格现在一团糟,或者至少对我来说是一团糟 我有一个初始化所有参数并创建事件的构造函数 我有一个巨大的状态属性,当用户通过由状态枚举控制的应用程序(即:断开连接、连接、设置、扫描)时,它会更新我所有表单控件的启用状态 我有3-10个通过属性访问的私有变量,其中一些在更改表单元素的值时有副作用 我有很多“U

我是一个自学编程的人,没有接受过任何正式的.NET编程培训

不久前,为了开发控制传感器的GUI程序,我启动了C#,该项目已经蓬勃发展。我只是想知道如何最好地在表单中组织代码,尤其是UI代码

我的表格现在一团糟,或者至少对我来说是一团糟

  • 我有一个初始化所有参数并创建事件的构造函数
  • 我有一个巨大的状态属性,当用户通过由状态枚举控制的应用程序(即:断开连接、连接、设置、扫描)时,它会更新我所有表单控件的启用状态
  • 我有3-10个通过属性访问的私有变量,其中一些在更改表单元素的值时有副作用
  • 我有很多“UpdateXXX”函数来处理依赖于其他UI元素的UI元素——即:如果传感器发生了更改,则更改波特率下拉列表。它们被分成若干区域
  • 我有很多事件调用这些更新函数
  • 我有一个背景工作人员负责所有的扫描和分析
我的问题是,这看起来像是一团糟,尤其是国有资产,而且越来越无法维护。另外,我的应用程序逻辑代码和UI代码在同一个文件中,在某种程度上是混合的,这似乎是错误的,这意味着我需要做大量的滚动来找到我需要的东西

如何构造.net表单


谢谢

这里有一个链接,指向一个经常使用的架构模式


我还将查找一些其他架构模式,并对这一模式进行更多研究,查找一些示例代码等。

查看模型视图演示器模式:

使用这种模式,表单背后的代码应该主要包含对presenter的简单级联调用,这反过来会改变模型,将事件级联回视图(有时通过presenter,具体取决于您的实现)

要点是:您的表单(视图)不应该包含任何状态信息;这将在演示者中,只要数据符合指定的合同,它就不应该关心从何处获取数据。这提高了可测试性,因为您可以轻松地在presenter上测试您的状态和数据,并解耦视图,允许PLAF、相同数据和类似数据的不同表示


祝你好运:)

一些快速建议:


尝试将所有非UI代码移出表单,如果可能,您只希望GUI代码处于实际表单中。如果一个属性有副作用,它可能是一个函数。您的State属性几乎肯定应该是一个方法,看看是否可以将其中的代码分解为单独的方法,这样每个状态只需调用一个函数。

对于复杂的表单,我通常将代码拆分为单独的文件。您可以使用“分部类”来完成此操作。每个源代码文件都是基于表单命名的。例如,MainForm.cs、MainForm.State.cs、MainForm.Update.cs、MainForm.Menu.cs等。如果我有许多复杂的表单,我将为每个表单创建一个子文件夹。这里的一个技巧是创建MainForm.Wip.cs表单。此分部类表单是您当前正在处理的代码。完成此代码后,可以重命名它或将代码移动到其他源代码文件

此外,我还将创建用户控件。这有代码重用的好处,它将许多功能移出了表单。请访问“使用.NET Framework开发自定义Windows窗体控件”


看看吧,没人在乎你的代码是什么样子的。“组织”之前需要考虑的一些问题。

您应该首先分析代码,以划分什么是应用程序逻辑,什么是UI逻辑。这两个文件不应该在同一个文件中。你的状态属性肯定不是UI逻辑,所以首先把它移出你的表单。这将帮助您清除表单代码


其次,阅读一些设计模式和原则。你可以找到一些很好的例子,在你的例子中,我会检查行为模式,更具体地说是状态和中介模式。它们不是解决问题的灵丹妙药,但它应该能让您更好地了解如何分割应用程序和UI逻辑。

我倾向于在用户控件或自定义控件中放入尽可能多的代码。组件更易于重用,表单代码更易于阅读

Usercontrols还可以处理和公开事件,使动态部分更容易与表单代码分离


您甚至可以创建自定义控件,这些控件在窗体上看不到,就像计时器一样

有许多模式可以帮助您分离应用程序中的逻辑,从而生成更干净、更易于维护的代码。MVP模式是一个很好的开始。它基于定义3个责任区域,即MVP M=模型、V=视图、P=演示者。如果您熟悉使用接口,您将很好,否则这将是一个很好的起点(回顾基本的OO原则:封装、抽象、多态)。MVP的基本原则是将应用程序逻辑放在演示者中。prescenter通过一个界面与视图(您的表单)对话,当用户与视图交互时,视图会回调演示者(我也使用一个界面)。该模型是解决方案的域对象层次结构,实现业务逻辑和实体关系

大多数UI模式(MVP、MCV等)都在尝试做同样的事情,将您的关注点分开。t以下是一个简单的例子:

//视图界面

interface IUserDetailsView
{

      string Username{set;get;}
      string FirstName{get;set;}
      string LastName{get;set;}
      UserDetailsPresenter Presenter{get;set;}
      void DisplayMessage(string message);


}
//视图实现 //一个标准的windows窗体,其中包含文本框、标签、组合框等

class UserDetailsView : Form, IUserDetails
{

      public string Username{set{txtUserName.text = value;}get{return txtUserName.text;}}
      public string FirstName{set{txtFirstName.text = value;}get{return txtFirstName.text;}}
      public string LastName{set{txtLastName.text = value;}get{return txtLastName.text;}}

      Public UserDetailsPresenter Presenter{get;set;}

      public void DisplayMaessage(string message)
      {
         MessageBox.Show(message);
      }

      private void saveButton_Click(object sender, EventArgs e)
      {
         Presenter.SaveUserDetails();

      }
}
//表示逻辑

类演示者UserDetailsPresenter {

}

//最后,模型

public class UserDetails
{

   public UserName {get;set;}
   public FirstName{get;set;}
   public LastName{get;set;}

   public bool IsValidUserDetails()
   {
       if(LastName == "Smith")
       {
          //We do not allow smiths, remember what happened last time ... or whatever
          return false;
       }

       return true;
   }

}
希望这能解释何鸿燊
public class UserDetails
{

   public UserName {get;set;}
   public FirstName{get;set;}
   public LastName{get;set;}

   public bool IsValidUserDetails()
   {
       if(LastName == "Smith")
       {
          //We do not allow smiths, remember what happened last time ... or whatever
          return false;
       }

       return true;
   }

}
#Region "_Edit"
    Private Sub _edit_VisibleChanged(...) Handles _edit.VisibleChanged
    End Sub
#End Region