【问题标题】:Get list of open windows form instance that are excuted from different assembly获取从不同程序集执行的打开窗口窗体实例列表
【发布时间】:2026-02-16 01:40:01
【问题描述】:

我有一个加载菜单的“加载器应用程序”,当用户单击菜单图像按钮时,会根据文本打开一个列表视图

(if text = employee)  
(Go to class A) 
(Go to class B) 
    ...
    ...
    (Show List View Window) 

如果他再次点击它再次打开的同一个按钮,我想阻止这种情况。 即,但这适用于 WPF 应用程序

【问题讨论】:

    标签: c# window instance


    【解决方案1】:

    如果你想要一个打开的表单列表,那就是Application.OpenForms。您可以迭代它,使用 GetType() 并检查 .Assembly 以从不同的程序集中找到它们。除此之外,我对这个问题并不完全清楚......

            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            List<Form> formsFromOtherAssemblies = new List<Form>();
            foreach (Form form in Application.OpenForms) {
                if (form.GetType().Assembly != currentAssembly) {
                    formsFromOtherAssemblies.Add(form);
                }
            }
    

    如果您只想跟踪自己打开的表单,请缓存该实例。或者,如果您使用“自有表格”,您可以按名称检查:

        private void button1_Click(object sender, EventArgs e) {
            foreach (Form form in OwnedForms) {
                if (form.Name == "Whatever") {
                    form.Activate();
                    return;
                }
            }
            Form child = new Form();
            child.Name = "Whatever";
            child.Owner = this;
            child.Show(this);
        }
    

    【讨论】:

    • 首先,感谢您的回复。参考你的第一个代码sn-p。问题是 Application.OpenForms (没有显示的表单,它只是一个加载器)以及 Assembly currentAssembly = Assembly.GetExecutingAssembly();看起来很有希望...代码应该是反向的..mmmm
    • Application.OpenForms 将返回 0 即因为它是加载器
    • 我不确定为什么你的主表单只是一个加载器会影响这里的结果......如果运行时知道表单,它应该出现在 Application.OpenForms - 除非你的意思是在不同的进程中运行 - 是这样吗?
    • 加载程序不是主要形式,它是一个显示 UI(菜单)并且不知道它显示什么的 exe。所以我需要得到正在执行的程序集但是然后呢?代码中涉及一些抽象......是否可以通过其他方式找到开放表单?
    【解决方案2】:
        NewProduct newproduct;
        private void button1_Click(object sender, EventArgs e)
        {
    
            if(!isOpened())
            {
                newproduct = new NewProduct();
                newproduct.Show();
            }
    
        }
        private bool isOpened()
        {
            foreach (Form f in Application.OpenForms)
            {
                if (f == newproduct)
                {
                    return true;
                }
            }
            return false;
        }
    

    【讨论】:

    • 请创建一个 WPF 应用程序,然后试试这个。我刚试了,没用。
    【解决方案3】:

    另一个简单的例子

    private Boolean FindForm(String formName)
        {
            foreach (Form f in Application.OpenForms)
            {
                if (f.Name.Equals(formName))
                {
    
                    f.Location = new Point(POINT.X, POINT.Y + 22);
                    return true;
                }
            }
    
            return false;
        }
    

    【讨论】:

      【解决方案4】:

      您可以使用命令模式。加载程序集将在加载的程序集中搜索命令。 对于每条命令,加载器都会创建菜单项(或任何您想要的),点击事件将运行具体的命令。

      该命令必须知道是应该创建新表单还是使用一些已经存在的表单。

      【讨论】:

        【解决方案5】:

        Mark Garvell 的回答帮助我弄清楚我应该做什么,但它需要针对 WPF 进行调整。

        (在我的情况下,我想在主窗口关闭时关闭所有不属于主窗口的窗口,但原理是一样的。)

        private void EmployeeMenuItemClick(object sender, RoutedEventArgs e)
        {
            bool found = false;
            foreach(Window w in Application.Current.Windows)
            {
                if(w.GetType() == typeof(EmployeeListViewWindow)
                {
                    found = true;
                    break;
                }
            }
            if(!found)
            {
                EmployeeListViewWindow ew = new EmployeeListViewWindow();
                ew.Show();
            }
        }
        

        【讨论】:

        • 能调整什么吗?新的/当前的窗口?是的,只需设置它的属性。
        • 哦,对了。这就是我为 WPF 所做的。我认为 WPF 应用程序没有 OpenForms 属性,所以我切换到 Application.Current.Windows