【问题标题】:Updating GUI components in class B from class A in c#从 C# 中的 A 类更新 B 类中的 GUI 组件
【发布时间】:2012-11-07 16:35:56
【问题描述】:

编辑:我看到我在这篇文章中得到了很多反对意见。我试图解释我试图做什么,我的错误在哪里以及想往哪个方向发展。我要求深入了解我做错了什么。如果您投反对票;请告诉我为什么,这样我就可以改进这个问题。谢谢。

我正在创建一个应用程序,其中有一个主窗体和几个不同的用户控件供用户使用。这有助于我拆分代码,管理程序的不同部分。以后扩展应用程序也很容易。

我正在尝试创建一个管理活动控件的类,我想在该类中调用一个函数,并将应该变为活动的表单作为参数。

一张图片可以说明我如何尝试设置此应用程序。 请注意,控制管理器类不是我在下面显示的代码中的单独类,而是主窗体的部分类。非常欢迎任何关于如何在图像中获得它的提示:)

管理所有活动表单的类如下所示: 请注意,所有用户控件都只是一个用户控件,上面有一些按钮/文本框等。还没有添加任何代码。

    public partial class STP2Main 
        {
// I make each UserControl accessable for the whole class
            SetupDeviceControl.SetupDevice SetupDev = new SetupDeviceControl.SetupDevice();
            GenConfigFileControl.GenConfigFileControl GenConfFile = new GenConfigFileControl.GenConfigFileControl();
            Monitoring.MonitoringControl Monitor = new Monitoring.MonitoringControl();
            GenEncKeyControl.GenEncKeyControl GenEncKey = new GenEncKeyControl.GenEncKeyControl();
            MenuControl.MenuControl MenuControl = new MenuControl.MenuControl();        

            public void SelectActiveWindow()
            {
                // Any active control should be hidden thats what this function does:
                HideCurrentActiveControl();
                // Check whether the window is already created
                if (!WindowExists())
                { // if not created; create the windows: 
                    switch (STP_Design.ProgramParameters.C.NextActiveControl)
                    {
                        case STP_Data.Data.SetupDeviceControl: // control 1:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
                            STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated = true;
                            SetupDev.Parent = this;
                            SetupDev.Location = new Point(3, 30);
                            SetupDev.Show();
                            SetupDev.BringToFront();
                            break;
                        case STP_Data.Data.MonitoringControl: //control 2:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
                            STP_Design.ProgramParameters.C.MonitoringControlIsCreated = true;
                            Monitor.Parent = this;
                            Monitor.Location = new Point(3, 125);
                            Monitor.Show();
                            Monitor.BringToFront();
                            break;
                        case STP_Data.Data.MenuControl: // control 3
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
                            STP_Design.ProgramParameters.C.MenuControlIsCreated = true;  
                            MenuControl.Location = new Point(3, 30);
                            MenuControl.Parent = this;
                            MenuControl.Show();
                            MenuControl.BringToFront();
                            break;
                    }
                }
                else
                { // window is already created so needs to be called to front again:
                    switch (STP_Design.ProgramParameters.C.NextActiveControl)
                    {
                        case STP_Data.Data.SetupDeviceControl:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
                            SetupDev.BringToFront();
                            break;
                        case STP_Data.Data.MonitoringControl:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
                            Monitor.Visible = true;
                            Monitor.BringToFront();
                            break;
                        case STP_Data.Data.AdvancedMenu:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.AdvancedMenu;
                            tabControl1.Visible = true;
                            tabControl1.BringToFront();
                            break;

                        case STP_Data.Data.MenuControl:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
                            MenuControl.Visible = true;
                            MenuControl.BringToFront();
                            break;
                    }

                }
                btnMenu.BringToFront();

            }
    // some functions which are called above are not shown; not relevant for this question
    }

我的经验如下:我完全没有错误。但控制根本没有改变。如果我调用一个窗口,它只会创建一次,因为我确实将它作为我的 Mainform 的部分类。 (我尝试了一个完整的单独类,但确实导致线程错误,由于我不是经验丰富的 c# 程序员,我试图避免使用部分类。)

我将添加另一个功能;它根本不做任何事情:

    private void HideCurrentActiveControl()
    {
        switch (STP_Design.ProgramParameters.C.CurrentActiveControl)
        {
            case STP_Data.Data.SetupDeviceControl:
                SetupDev.Visible = false;
                break;
            case STP_Data.Data.MonitoringControl:
                tabControl1.Visible = false;
                Monitor.Visible = false;
                break;
            case STP_Data.Data.GenConfFileControl:
                GenConfFile.Visible = false;
                break;
            case STP_Data.Data.GenEncKeyControl:
                GenEncKey.Visible = false;
                break;
            case STP_Data.Data.MenuControl:
                MenuControl.Visible = false;
                break;
            case STP_Data.Data.AdvancedMenu:
                tabControl1.Visible = false;
                break;
            default:
                tabControl1.Visible = false;
                break;

        }
    }

我已经尝试调试这部分代码并执行语句,但我没有看到任何变化。

我想我已经展示了我想要做什么;以及我如何尝试做到这一点。我的问题是:我如何访问这些表单,以便我可以从一个单独的类(或者在这种情况下是主表单的部分类)管理它们。

然后我有最后一个函数,它做了一些奇怪的事情。在调用 SelectActiveWindow() 函数之前,我将变量 STP_Design.ProgramParameters.C.NextActiveControl 更新为例如:...AdvancedMenu。 (这是在那之前...MenuControl)但它总是表明它仍然是MenuControl。除了在我启动函数之前,我的代码中没有任何地方可以更改该值。 (我也尝试将 nextcontrol 作为函数 SelectActiveWindow() 的参数,但这也是一样的)

    private bool WindowExists()
    {
        switch (STP_Design.ProgramParameters.C.NextActiveControl)
        {
            case STP_Data.Data.SetupDeviceControl:
                if (STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated)
                    return true;
                else
                    return false;
            case STP_Data.Data.MonitoringControl:
                if (STP_Design.ProgramParameters.C.MonitoringControlIsCreated)
                    return true;
                else
                return false;
            case STP_Data.Data.GenConfFileControl:
                if (STP_Design.ProgramParameters.C.GenConfFileIsCreated)
                    return true;
                else
                    return false;
            case STP_Data.Data.GenEncKeyControl:
                if (STP_Design.ProgramParameters.C.GenEncKeyControlIsCreated)
                    return true;
                else
                    return false;
            case STP_Data.Data.AdvancedMenu:
                return true;
            case STP_Data.Data.MenuControl:
                if (STP_Design.ProgramParameters.C.MenuControlIsCreated)
                    return true;
                else
                    return false;

            default:
                return false;
        }
    }

我正在寻找的摘要: 我有一个主窗体,其中显示不同的用户控件。我正在尝试创建一个单独的类,可以从我的项目中的每个控件/窗体访问。此类应管理显示的控件。在上面的代码中,我说明了我是如何尝试这样做的,但这并没有产生预期的结果。

【问题讨论】:

  • 控制标识符默认是private。您可以在“属性”窗口中更改修饰符属性。或者只是向 a 类添加一个公共方法。
  • 刷新();在更改某些内容后重新绘制页面是一件方便的事情。

标签: c# .net class


【解决方案1】:

好的,现在我了解了所需的上下文。我们实际上在我的程序中做了一些非常相似的事情。以下是我们如何做到这一点的基本大纲......

布局

在主窗体上,我们有一个 Panel 容器,我们称之为pnlMain。正是这个控件,我们从中添加和删除活动用户控件。我们在代表curActiveControl的表单上还有一个全局级别的UserControl对象。

代码

当用户通过其中一个菜单选择一个窗口时,我们运行一个看起来像这样的函数

switch (UserSelection)
{
    case "Page 1":
        if(curActiveControl.GetType() != typeOf(Page1Control))
        {
            pnlMain.Controls.Remove(curActiveControl);
            curActiveControl = new Page1Control();
            //do setup and configuration things
            pnlMain.Controls.Add(curActiveControl);
        }
        //do some post processing things
        break;
    //other pages/specific page controls
}

Refresh();

这种特定方法的缺点是页面本身不是持久的,因此如果您希望在会话中而不是仅在页面上激活条目或变量,则必须将它们存储在其他一些全局变量中对象并从用户控件的 Load 或 Constructor 方法重新加载它们。

您可以做同样的事情,但不是每次都为curActiveControl 创建一个新控件实例,您只需将其替换为新控件的备用实例即可。不过要小心引用和覆盖,这不是我个人之前尝试过的。

我们使用的方法中的关键是保存用户控件的面板。我们无需调整大量用户控件的可见性和 Z-Order,而是简单地更改主面板中显示的控件,而其他控件甚至在任何给定时间点都不存在。

另一个问题是这个功能直接在我们的主窗体上。我不知道这作为另一个部分课程会有多好。不过绝对值得一试。

【讨论】:

  • 您好,谢谢您的回答。由于new 关键字,这将不起作用。如果我创建一个新类,我将无法访问现有表单上的控件(我想要的),但我可以访问新表单的控件。
  • 所以你需要方法2,你必须以某种方式将你需要的特定引用传递给类。您可以在通过构造函数创建类时执行此操作,然后通过某种公共指针,或在方法级别使用方法参数...但是您必须专门提供您需要的参考,否则代码不能没看到。
  • 我已经更新了我的问题,因为我觉得这对社区没有建设性。我已经对其进行了扩展,但我认为其中包含更多信息以供进一步使用。
  • 我根据对问题的更改更改了整个答案。看看=D
  • 感谢您的解释!正如您所说,页面本身不是持久的,可以通过更改可见性来更改。这就是我所做的。我还发现了错误的位置(经过 2 天的纠缠终于)。我错过了一个“=”我试过var temp this.Parent as STP2Main并像temp.SelectActiveWindow()这样调用函数,但我一直在var temp... 上遇到错误,在tempthis.Parent之间添加一个“=”解决了这个问题。我对把这个函数放在一个单独的类而不是主窗体中非常感兴趣。你知道我可以阅读更多相关信息的好资源吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-07
  • 2017-04-19
  • 2013-06-12
  • 1970-01-01
  • 2017-12-28
  • 1970-01-01
相关资源
最近更新 更多