12

论坛; 我是一个新手,正在编写一些代码。我想知道使用包含其他类和函数的单独 .cs 文件的最佳方法。作为一个基本功能的例子,想要点击一个清除按钮并让它清除表单上的所有字段。代码分为三个 .cs 文件。Main.cs、MainForm.Designer.cs 和 btClear.cs。

MainForm.Designer.cs 包含设计师自动创建的代码,包括清除按钮和我想清除的文本框。

我想要清除 btClear.cs 中包含的文本框的代码。我知道将此代码简单地放在 MainForm.Designer.cs 中很容易,但是我想将其用作模板,以便将单独的 .cs 文件用作标准做法。

有人可以给我一个如何做到这一点的例子吗?

4

7 回答 7

6

大多数 .net 程序员的做法是:

  • 将所有代码留在里面MainForm.cs,但声明一个新方法来分离执行清除的代码。

我总是留在事件处理程序方法(双击按钮时VS生成的那个)代码来更改鼠标光标(以防我调用的代码需要几秒钟或更长时间才能运行)并捕获所有未处理的异常,并将我的逻辑放在一个单独的私有方法中:

partial class MainForm : Form // this is MainForm.cs
{
    // This is the method VS generates when you double-click the button
    private void clearButton_Click(object sender, EventArgs e)
    {
        this.Cursor = Cursors.WaitCursor;
        try
        {
            ClearForm();
        }
        catch(Exception ex)
        {
            // ... have here code to log the exception to a file 
            // and/or showing a message box to the user
        }
        finally
        {
            this.Cursor = Cursors.Default;
        }
    }

    private void ClearForm()
    {
        // clear all your controls here
        myTextBox.Clear();
        myComboBox.SelectedIndex = 0;
        // etc...
    }
}

在我看来,如果你想在 .net 中遵循传统的做事方式,你应该坚持第一个例子。

当代码不属于表单逻辑(例如数据访问代码或业务逻辑)时,建议将代码移出表单 .cs 文件。在这种情况下,我认为清除表单控件不符合业务逻辑。它只是表单代码的一部分,应该保留在MainForm.cs.

但是如果你真的想把ClearForm方法放在另一个 .cs 文件中,你可以创建一个新类并将ClearForm方法移到那里。您还需要将每个控件的 Modifiers 属性更改为 Public,以便您的新类可以从 MainForm 外部访问它们。像这样的东西:

public class FormCleaner // this is FormCleaner.cs
{
    public void ClearForm(MainForm form)
    {
        // clear all your controls here
        form.myTextBox.Clear();
        form.myComboBox.SelectedIndex = 0;
        // etc...
    }
}

您必须将主表单代码更改为:

partial class MainForm : Form // this is MainForm.cs
{
    // This is the method VS generates when you double-click the button
    private void clearButton_Click(object sender, EventArgs e)
    {
        this.Cursor = Cursors.WaitCursor;
        try
        {
            FormCleaner cleaner = new FormCleaner();
            cleaner.ClearForm(this);
        }
        catch(Exception ex)
        {
            // ... have here code to log the exception to a file 
            // and/or showing a message box to the user
        }
        finally
        {
            this.Cursor = Cursors.Default;
        }
    }
}

但是请注意,您的FormCleaner班级必须了解您的MainForm班级才能知道如何清除表单的每个控件,或者您需要提出一个通用算法,该算法能够遍历Controls任何表单的集合以清理它们:

public class FormCleaner // this is FormCleaner.cs
{
    // 'generic' form cleaner
    public void ClearForm(Form form)
    {
        foreach(Control control on form.Controls)
        {
            // this will probably not work ok, because also
            // static controls like Labels will have their text removed.
            control.Text = "";
        }
    }
}

正如其他人所说,MainForm.Designer.cs它是机器生成的,你永远不应该把自己的代码放在那里。

于 2009-02-21T09:54:00.667 回答
5

你可以partial为你的班级使用一个班级MainForm,因为这已经在MainForm.csand中完成了MainForm.Designer.cs

btnClear.cs

public partial class MainForm
{
   private void clearForm(object sender, EventArgs e)
   {
     // ...
   }
}

MainForm.cs并在或中注册活动MainForm.Designer.cs

this.btnClear.click += clearForm;

编辑:

如果您想要一种通用的方法,您可以将Tag控件的属性设置为默认值。使用扩展方法,您可以执行类似的操作formGroup.Reset();

using System.Windows.Forms;

public class ControlExtensions
{
  public void Reset(this Control control)
  {
    if (control.Tag != null)
    {
      if (control is TextBoxBase && control.Tag is string)
      {
        control.Text = control.Tag as string;
      }
      else if (control is CheckBox && control.Tag is bool)
      {
        control.Checked = control.Tag as bool;
      }
      // etc
    }

    foreach (Control child in control.Children)
      child.Reset();
  }
}
于 2009-02-21T05:30:38.053 回答
4

每个 .cs 文件一个类是一个很好的规则。

除非您打算封装到可重用的类中,否则我不会将特定于页面的功能分离到单独的 .cs 文件中。

编辑:

将清除函数放在按钮的 OnClick 事件中。没有理由将其分开。

.aspx 文件:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SimpleWebTest._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="ClearButton" runat=server onclick="ClearButton_Click" Text="Button" />
    </div>
    </form>
</body>
</html>

.cs 文件

using System;

namespace SimpleWebTest
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e) { }

        protected void ClearButton_Click(object sender, EventArgs e)
        {
            using (ComplexOperationThingy cot = new ComplexOperationThingy())
            {
                cot.DoSomethingComplex();
            }
        }
    }
}

ComplexOperationThingy.cs:

using System;

namespace SimpleWebTest
{
    public class ComplexOperationThingy
    {
        ComplexOperationThingy() { }

        public void DoSomethingComplex()
        {
            //Do your complex operation.
        }
    }
}
于 2009-02-21T05:26:54.553 回答
1

做起来相当简单。在您的 btClear.cs 文件中,只需生成一个类定义,如:

public class MyUtility
{
    public static void ClearContents(IEnumerable<Control> controls)
    {
        //TODO: Code that clears contents of controls passed
    }
}

然后,您可以从通过以下方式引用生成的类所包含的命名空间的任何位置调用它:

MyUtility.ClearContents(SomeControlCollection);

我希望我没有完全错过你的意图。

于 2009-02-21T05:31:31.093 回答
1

一般来说,您不应该将代码放在 MainForm.designer.cs 文件中。Visual Studio 使用 *.designer.cs 文件来连接在表单上实际放置控件的所有繁琐管道。

您想用来与表单上的控件交互的任何代码都应该放在 MainForm.cs 文件中。因此,如果您想要一个函数来清除表单上的控件,那么您应该将代码放在那里。

如果您编写的代码清楚表单上的控件可在其他项目中重用,那么您应该将其放在另一个可以链接到其他项目的 .cs 文件中。

正如 Chris 所说,通常每个 .cs 文件放置一个类也是一个好主意。当你这样做时,文件应该有它包含的类的名称。因此,如果您有一个名为 MyButtonHelpers 的类,则源文件应命名为 MyButtonHelpers.cs。

于 2009-02-21T05:37:29.440 回答
0

我发现最好不要直接编辑 .Designer.cs 文件,尤其是从源代码管理的角度来看。您可以使用部分类来包含相关代码;在这种情况下,您可以使用 MainForm.Designer.cs 作为如何完成部分类的示例(例如,部分类 MainForm{})。

如果您通过 Windows 窗体设计器添加事件处理程序,它应该自动将它们放置在 MainForm.cs,而不是 MainForm.Designer.cs。如果您的项目增长到任何显着的规模,我经常发现创建多个部分类文件很有用,一个用于每个主要功能组。这使得查找特定功能(和相关功能)变得更加容易。

于 2009-02-21T05:36:36.760 回答
0

C#(和许多其他语言)中的约定是每个类一个文件(通常每个文件一个类)。这条规则当然有例外,但是将一个类拆分到多个文件中应该很少见,而不是标准做法。

您在评论中提到,您预见到比您给出的示例更“复杂的操作”。你设想什么样的操作?只要您只是在谈论处理表单控件,逻辑就属于表单的 .cs 文件(在本例中是 MainForm.cs,而不是MainForm.designer.cs - 正如其他人所说,您应该永远不要修改 .designer 文件)。

如果您的表单变得过于复杂,那么将其分解为单独的自定义控件可能是有意义的。这将允许您保持源文件更小,但是(因为每个 Control 映射到一个类)您将遵守一个类 <-> 一个文件约定。

于 2009-02-21T07:08:50.673 回答