有没有办法缩短这段代码? C#winforms

时间:2010-09-27 00:21:46

标签: c#

我正在学习Windows窗体中的MDI表单,我正在使用这个简单的应用程序: alt text

每个ToolStripMeniItem调用特定表单的单个实例,但正如您所看到的(请参阅我的代码),我的代码对于每个ToolStripMeniItem都是重复的,我该如何缩短它?

        public static Form IsFormAlreadyOpen(Type FormType)
        {
            foreach (Form OpenForm in Application.OpenForms)
            {
                if (OpenForm.GetType() == FormType)
                    return OpenForm;
            }
            return null;
        }

        private void form1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form1 f1 = null;
            if (IsFormAlreadyOpen(typeof(Form1)) == null)
            {
                f1 = new Form1();
                f1.MdiParent = this;
                f1.Show();
            }
            else
            {
                Form selectedForm = IsFormAlreadyOpen(typeof(Form1));
                foreach (Form OpenForm in this.MdiChildren)
                {
                    if (OpenForm == selectedForm)
                    {
                        if (selectedForm.WindowState == FormWindowState.Minimized)
                        {
                            selectedForm.WindowState = FormWindowState.Normal;
                        }
                        selectedForm.Select();
                    }
                }
            }
        }

        private void form2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 f2 = null;
            if (IsFormAlreadyOpen(typeof(Form2)) == null)
            {
                f2 = new Form2();
                f2.MdiParent = this;
                f2.Show();
            }
            else
            {
                Form selectedForm = IsFormAlreadyOpen(typeof(Form2));
                foreach (Form OpenForm in this.MdiChildren)
                {
                    if (OpenForm == selectedForm)
                    {
                        if (selectedForm.WindowState == FormWindowState.Minimized)
                        {
                            selectedForm.WindowState = FormWindowState.Normal;
                        }
                        selectedForm.Select();
                    }
                }
            }
            // and so on... for the other ToolStripMeniItem
        }

4 个答案:

答案 0 :(得分:5)

A generic function是一个函数,它将使用一组将由调用者定义的类型

所以代替 int doubleIt(int a) { return a*2; } 你可以说
T doubleIt<T>(T a){ return a*2; }

这意味着您可以定义一个可以像这样调用的函数:

int intResult = doubleIt(...pass in a int..);
double doubleResult = doubleIt(...pass in a double..);
float floatResult = doubleIt(...pass in a float..);

因此,对于您的代码,您创建了一个方法,该方法将您创建的表单类型作为T的值。

但是编译器不知道T是一个表单并且你可以在其上调用new,所以你必须将可以作为T传递的类型与where子句相提并论T表示必须是一个表单,必须是您可以访问的构造函数

因此,您可以使用专用于您需要的f1类型的通用函数替换核心功能。

因此,您可以使用Form f1 = null;

传递的通用类型代替T f1 = null;
private void ClickEvent<T>(object sender, EventArgs e) where T: Form, new() {
            T f1 = null;
    .
    .
    .
 }

然后从真实的事件处理程序中调用此方法

private void form1ToolStripMenuItem_Click(object sender, EventArgs e)       {
            ClickEvent<Form1>(sender, e)
        }

        private void form2ToolStripMenuItem_Click(object sender, EventArgs e) {
           ClickEvent<Form1>(sender, e) 
        }

所以你最终得到的结果是:

public static Form IsFormAlreadyOpen(Type FormType)
{
    foreach (Form OpenForm in Application.OpenForms)
    {
        if (OpenForm.GetType() == FormType)
            return OpenForm;
    }
    return null;
}

private void ClickEvent<T>(object sender, EventArgs e) where T: Form, new() 
    {
    T f1 = null;
    if (IsFormAlreadyOpen(typeof(T)) == null)
    {
        f1 = new T();
        f1.MdiParent = this;
        f1.Show();
    }
    else
    {
        Form selectedForm = IsFormAlreadyOpen(typeof(T));
        foreach (Form OpenForm in this.MdiChildren)
        {
            if (OpenForm == selectedForm)
            {
                if (selectedForm.WindowState == FormWindowState.Minimized)
                {
                    selectedForm.WindowState = FormWindowState.Normal;
                }
                selectedForm.Select();
            }
        }
    }
}

    private void form1ToolStripMenuItem_Click(object sender, EventArgs e)       {
        ClickEvent<Form1>(sender, e)
    }

private void form2ToolStripMenuItem_Click(object sender, EventArgs e) {
   ClickEvent<Form1>(sender, e) 
}

额外:如果你可以使用Linq,那就是这样的。

  using System.Linq;

             public static Form IsFormAlreadyOpen(Type FormType)        {       
                return Application.OpenForms.Where( f => f.GetType() == FormType).FirstOrDefault();
            }

            private void ClickEvent<T>(object sender, EventArgs e) where T: Form, new() 
            {
                T selectedForm = IsFormAlreadyOpen(typeof(T); 
                if (selectedForm == null)             {
                    (new T() { MdiParent = this; }).Show()
                }
                else {  
                    this.MdiChildren.Where(o => o == selectedForm).ForEach(
                        openForm => { 
                            selectedForm.WindowState = (selectedForm.WindowState == FormWindowState.Minimized) ? FormWindowState.Normal : selectedForm.WindowState;
                            openForm.Select();
                        }
                    );
                }
            }
            private void form1ToolStripMenuItem_Click(object sender, EventArgs e)       {
                ClickEvent<Form1>(sender, e)
            }

            private void form2ToolStripMenuItem_Click(object sender, EventArgs e) {
               ClickEvent<Form2>(sender, e) 
            }

您可以采取其他措施来缩短此代码,但使用泛型和linq将是最有效的。

答案 1 :(得分:2)

可能更容易使用MenuItem类的'标记'属性并使用它,并动态构建菜单项,将其添加到MenuStrip中,并使用单个Click事件处理程序< strong> 所有 菜单项,然后是找出使用了哪个标签的问题,例如你可以将标签设置为这样的表格

menuItem = new MenuItem("Form 1");
menuItem.Tag = Form1;
menuItem.Click += new EventHandler(frmMDI_FormHandler_Click);
frmMDI.MenuStrip.Add(menuItem);

答案 2 :(得分:2)

我在考虑将通用功能分解为通用方法。它确实使用了泛型和Activator.CreateInstance,但除此之外,下面的代码几乎都是OP的代码,只是重构了。

private void form1ToolStripMenuItem_Click(object sender, EventArgs e)
{
    OpenForm<Form2>();
}

private void OpenForm<T>() where T : Form
{
    T form = null;

    if (IsFormAlreadyOpen(typeof(T)) == null)
    {
        form = Activator.CreateInstance<T>();
        form.MdiParent = this;
        form.Show();
    }
    else
    {
        Form selectedForm = IsFormAlreadyOpen(typeof(T));
        foreach (Form OpenForm in this.MdiChildren)
        {
            if (OpenForm == selectedForm)
            {
                if (selectedForm.WindowState == FormWindowState.Minimized)
                {
                    selectedForm.WindowState = FormWindowState.Normal;
                }
                selectedForm.Select();
            }
        }
    }
}

答案 3 :(得分:0)

hackish缩短这段代码的方法(我不认为这就是你的意思:p)

另请注意:“IsXYZ(val)”意味着布尔反应......想一想。尝试“GetOpenForm(Type FormType)”

public static Form IsFormOpen(Type FormType) {
  foreach (Form OpenForm in Application.OpenForms) 
    if (OpenForm.GetType() == FormType)
      return OpenForm;
  return null;
}

请注意,它有助于定义“缩短代码”...您只是意味着重复为新案例生成新代码所需的击键吗?

另外,请注意,结合Preet和Tommie的答案,您可以查看sender并获取调用方法的类型,从而允许您在那里自定义逻辑。按类型检查每个表单的时髦逻辑是导致代码看起来过于复杂的原因。如果有另一种方法来识别打开的窗口,那可能会对你有利。