【问题标题】:New panel not opening on Windows Form after triggering click event触发点击事件后,新面板未在 Windows 窗体上打开
【发布时间】:2021-10-18 04:09:19
【问题描述】:

我有一个 Windows 窗体应用程序。 我创建了一个自定义UserControl,它扩展了Panel。 在我的一个表单中,有一个按钮可以在单击时打开该面板。

但是,点击后,还是看不到表单上显示的面板。

表格代码

public partial class IngredientMenu : Form
    {
        public IngredientMenu()
        {
            InitializeComponent();
        }

        private void btnOpenRegisterBasePanel_Click(object sender, EventArgs e)
        {
            BaseIngredientPanel baseIngredientPanel = new BaseIngredientPanel();
            baseIngredientPanel.Location = new Point(257, 63);
            baseIngredientPanel.Show();
            baseIngredientPanel.BringToFront();
            Console.WriteLine("panel should open");
            Console.WriteLine(baseIngredientPanel.Visible);
            Console.WriteLine(baseIngredientPanel.Location);
        }
    }

面板代码

public partial class BaseIngredientPanel : UserControl
    {
        public BaseIngredientPanel()
        {
            InitializeComponent();
        }

        private void btnRegisterBaseIngredient_Click(object sender, EventArgs e)
        {
            IngredientContext ingredientContext = new IngredientContext();
            if (ingredientContext.RegisterIngredient(txtName, txtUnit, lblBaseIngredientNameValidation, lblBaseIngredientUnitValidation))
            {
                MessageBox.Show("Ingredient Registered."
                        , "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtName.Text = "";
                txtUnit.Text = "";
            }
            else
            {
                MessageBox.Show("There are errors in the form fields."
                        , "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void BaseIngredientPanel_Load(object sender, EventArgs e)
        {
            Console.WriteLine("I AM OPEN");
        }
    }

此外,即使在单击之后,“我已打开”消息也不会出现,因此通常它似乎甚至没有加载控件。

如何在单击按钮后打开面板?我宁愿不手动将面板拖到设计器中,因为我需要有 5 个面板,而设计器只会尝试将它们像俄罗斯娃娃一样装箱。

【问题讨论】:

  • 您需要将它添加到父控件的集合中。或者设置它的 Parent 属性。不需要 Show,因为 visible 默认为 true。
  • 现在,如果你想隐藏它,你可以这样做,然后根据需要再次显示..

标签: c# winforms


【解决方案1】:

所有 UI 控件都需要通过 Controls.Add() 方法拥有它们所属的父级。 父级可以是表单或其他控件(并非所有控件都接受子级)。例如您的面板可以是文本框、组合框、标签等的父级。

private void btnOpenRegisterBasePanel_Click(object sender, EventArgs e)
{
    BaseIngredientPanel baseIngredientPanel = new BaseIngredientPanel();
    baseIngredientPanel.Location = new Point(257, 63);

    //Add user panel to form.  
    this.Controls.Add(baseIngredientPanel);

    //You will probably not need these two rows any more.  Try it out!  But make sure your usercontrol has Visible = true.
    baseIngredientPanel.Show();
    baseIngredientPanel.BringToFront();
}

编辑:

在下面的评论中回答您的问题

如果您需要同时进行许多 UI 更改,那么最好也使用 this.SuspendLayout()this.ResumeLayout() 来暂时暂停 UI 逻辑。在这种情况下,这将有助于提高性能。详情请见https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.suspendlayout?view=windowsdesktop-5.0

如果您需要在添加控件后的某个阶段删除它们,那么您有两种选择。

  1. 创建一个单独的List<BaseIngredientPanel> 以(也)存储您的 在将它们添加到表单时进行控制。这使用此列表查找 并通过this.Controls.Remove() 方法删除它们
  2. 在创建 BaseIngredientPanel 时为其指定一个唯一名称,并且 使用它通过 this.Controls.Remove() 方法。所有控件都已经有一个 Name 属性,所以你可以使用它。

【讨论】:

  • 我是否应该担心将控件添加到集合中的次数过多?我假设每次点击都会添加它,这最终不会减慢 UI 的速度吗?当我需要关闭控件并打开另一个控件时,是否有一种安全的方法可以移除控件?
【解决方案2】:

如果你想展示一个Form,这个类应该是从Form派生的。您的BaseIngredientPanel 不是表单,而是用户控件。

UserControls 类似于其他控件,如按钮、组合框、菜单、DataGridViews 等。通常您使用 Visual Studio 设计器在窗体上显示它们。在极少数情况下,您会以编程方式执行此操作。

我创建了一个扩展 Panel 的自定义 UserControl。

你真正想要什么:

  • 我想创建一种特殊的面板,它的行为类似于标准面板,只有很小的差异。我班的用户几乎可以使用我的特殊面板的所有属性:派生自类面板
  • 我想创建一种特殊的面板,其行为类似于标准面板。我想控制我的特殊 Panel 的用户可以调用哪些方法:创建一个派生自 UserControl 的类并在其上放置一个 Panel。
  • 我想创建一个表单,我想在其上放置一个面板。这个面板有一些我只在这个表单上使用的行为。

如果您想创建一种特殊的面板,可以在多个表单上重复使用,请使用派生。您是从 Panel 还是从 UserControl 派生取决于您希望您的类有多傻,以及您的类的用户可以调用多少 Panel 方法。

如果您的特殊面板仅用于一个表单,请不要费心创建特殊的面板类。创建一个包含面板的表单。

在特殊表单上使用标准面板

如果您决定不必重用此面板的行为,您可以将其放在新表单上。使用 Visual Studio Designer 创建表单并在其上放置一个面板。订阅您想要做出反应的 Panel 事件。

如果您希望表单也有一个 Button,还可以使用 Visual Studio Designer 添加 Button 并订阅事件 Button_Clicked。

要显示 PanelForm,您必须决定 PanelForm 是模型还是非模型。

  • 模态:操作者只能使用这个表单,直到它被关闭。他不能使用此应用程序的其他形式。这是迄今为止最常用的一种Form:在菜单选择或按钮单击时:显示PanelForm,使用PanelForm,关闭PanelForm,之后父窗体可以读取PanelForm 的结果并采取相应的行动。模态对话框使用 Form.ShowDialog 显示。
  • 无模式:显示 PanelForm 时,操作员可以切换回父窗体并与之交互。这不经常使用。您可以使用它来显示有关父窗口或应用程序状态的一些额外信息,例如鼠标的位置,或您将绘制的选定形状。使用 Form.Show() 显示无模式对话框。请记住,在关闭父窗体之前,您必须关闭无模式对话框

显示模态

OpenFileDialog 表单就是一个很好的例子

在您的父表单中:

using (var form = new OpenFileDialog())
{
    // set properties of the OpenFileDialog before showing
    form.InitialDirectory = this.GetInitialDirectory();
    form.DefaultExt = ".txt";
    ...

    // Show the Form as a modal box and wait until it is Closed
    DialogResult dialogResult = form.ShowDialog(this);

    // the operator has closed the form. Interpret the result:
    if (dialogResult == DialogResult.OK)
    {
        string fileName = form.FileName();
        this.OpenFile(fileName);
    }
}

无模式:操作员可以切换回这种形式

private MyPanel PanelForm {get; set;} = null;

private void ShowMyPanel()
{
    if (this.PanelForm != null) return;   // panel already shown

    this.PanelForm = new MyPanel();

    // set properties:
    this.PanelForm.DisplayedItems = ...

    // show the PanelForm
    this.PanelForm.Show();
}

操作员可以切换回此表单,并可能关闭此表单。在这种情况下,您将不得不关闭 PanelForm:

private void CloseMyPanel()
{
    if (this.MyPanel != null)
    {
        this.MyPanel.Close();
        this.MyPanel.Dispose();
        this.MyPanel = null;
    }
}

private void OnFormClosing(object sender, ...)
{
    // if MyPanel is shown, is it allowed to Close this form AND myPanel
    // or should you warn the operator to close MyPanel first?

    if (this.MyPanel != null)
    {
         this.CloseMyPanel();     // close immediately

         // or:
         MessageBox.Show(..., "Please close Panelbox first");
    }
}

当然,如果操作员关闭面板框,您也应该做出反应。在显示面板框之前:

this.MyPane.Closed += OnMyPanelClosed;

private void OnMyPanelClosed(object sender, ...)
{
    if (object.ReferenceEquals(sender, this.MyPanel)
    {
        // my panel is closed
        this.MyPanel = null;

您无法处置面板,因为它仍在使用中。面板显示关闭时自行处理。

特别小组类

如果你有一个特殊面板类(派生自 Panel 或 UserControl),那么编译后,面板控件在 Visual Studio Designer 的工具箱中可见。

你应该使用Visual Studio Designer创建一个Form并将面板放在Form上:

class MyPanelForm : Form
{
    public MyPanelForm()
    {
        InitializeComponent();

如果您使用 Visual Studio Designer 添加了特殊面板,那么您将在 InitializeComponent 中找到它。你也可以在构造函数中自己添加。在这种情况下,不要忘记将其添加到this.components,这样您的面板就会在 MyPanelForm 被释放时被释放。

要显示 MyPanelForm,请使用 ShowDialogShow,如上一节所述。

【讨论】:

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