【问题标题】:call Function in Form1 from Form2 in c#从 C# 中的 Form2 调用 Form1 中的函数
【发布时间】:2012-05-21 13:19:48
【问题描述】:

我在 Form1 中有以下函数,希望在单击 Form2 中的按钮时调用它。

   public object GetStudents()
    {
        using (var DB = new myView1())
        {
            var studentList = (from s in DB.View123
                            select new { s.StudentName, s.StudentNumber, s.ClassName, s.StreamName, s.ParentName }).ToList();
            dataGridViewStudents.DataSource = students;
            return students.ToList();
        }
    }

上面的函数在 Form1 中,我如何从 Form2 中的 button_Click 事件中调用它。这在 VB.NET 中很简单

【问题讨论】:

  • 你在某处有Form1 类型的变量吗?在 C# 和 VB.Net 中大致相同。
  • 这是一颗宝石!结合您的问题,这是混合表示层和我长期以来看到的业务逻辑的最佳示例。给你一个正经的答复:你为什么不把数据检索代码放到它自己的类中呢?在这种情况下,两种形式都可以使用它,而无需您将要引入的交叉依赖关系。
  • @Thorsten Dittmar:但除了宝石方面,你如何简单地完成我的要求? ---- 假设这是一个快速演示,代码将被重构!
  • @SQL.NET Warrior,如果您必须就一个应用程序提出这么多问题,不妨考虑尝试一个更基本的项目。
  • 好吧,将Form1 的实例传递给Form2 或在您需要的地方创建Form1 的实例。但是为什么不立即重构它......

标签: .net winforms c#-4.0


【解决方案1】:

在 C# 中也很简单。您只需要一个Form1 的实例,然后您就可以在该实例上调用此方法。

但是,有更好的方法。这段代码实际上并不属于在表单上。表单用于 UI 交互,而不是用于业务逻辑和数据访问。您最好将此代码移动到两个表单都可以访问的公共位置。

创建一个数据访问类。像这样的:

public class StudentRepository
{
    public static object GetStudents()
    {
        using (var DB = new myView1())
        {
            var studentList = (from s in DB.View123
                        select new { s.StudentName, s.StudentNumber, s.ClassName, s.StreamName, s.ParentName }).ToList();
            dataGridViewStudents.DataSource = students;
            return students.ToList();
        }
    }
}

还要注意,该方法现在是static,这意味着它不需要调用实例。 (这就像 VB 中的 Shared 关键字。)所以您的表单可以调用:

var students = StudentRepository.GetStudents();

您想要解决的另一件事是返回类型,尽管它超出了此问题的范围。 object 不是很具体。你应该有一个Student 类并且该方法应该返回IList<Student>。像这样的:

public class Student
{
    public string StudentName { get; set; }
    public int StudentNumber { get; set; }
    public string ClassName { get; set; }
    public string StreamName { get; set; }
    public string ParentName { get; set; }
}

和:

public class StudentRepository
{
    public static IList<Student> GetStudents()
    {
        using (var DB = new myView1())
        {
            var studentList = (from s in DB.View123
                        select new Student { StudentName = s.StudentName, StudentNumber = s.StudentNumber, ClassName = s.ClassName, StreamName = s.StreamName, ParentName = s.ParentName }).ToList();
            dataGridViewStudents.DataSource = students;
            return students.ToList();
        }
    }
}

我对字段的类型做了一些假设,如果它们是错误的,您应该能够更正这些假设。如果结果不变(也就是说,如果它只是学生的枚举而不是要添加、删除等的列表),您甚至可能希望它返回 IEnumerable&lt;Student&gt; 而不是 IList&lt;Student&gt;

您可以在这里做更多的事情,例如为其他数据元素创建一个对象,例如 Class(可能需要一个不同的名称,只是为了干净)、ParentStream 等。 (想一想,其中一些可能需要更好的名称。您的变量命名通常需要一些工作。Form1myView1 之类的东西不能很好地传达意图。)

【讨论】:

    【解决方案2】:

    您需要为您的Form2 实例提供对Form1 实例的引用,此时它就像form1.GetStudents() 一样简单。

    如果Form1 是你的主要形式,你可以简单地做

    var students = ((Form1)ApplicationContext.MainForm).GetStudents();
    

    但是,此代码的几个部分会散发出难闻的代码气味:

    • Form 中的数据库代码(实际上不是表单的责任)
    • 返回object 而不是IList 的方法
    • 在没有上下文的情况下不清楚 ApplicationContext.MainForm 是什么(推论:不要这样做)

    恕我直言,您应该借此机会重构现有代码并使其符合可接受的做法。

    【讨论】:

    • 感谢您的建议,一定会这样做
    【解决方案3】:

    我没有使用过 C# 但它应该类似于 VB.Net,因为它仍然在同一个框架上。您是否尝试过将函数放在单独的资源文件中并将其添加到项目中?您无法调用该函数的原因似乎是由于它们以不同的形式存在范围问题。资源文件应该处理好这一点,并且由于它减少了混乱,它往往使代码更容易维护

    【讨论】:

      猜你喜欢
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      相关资源
      最近更新 更多