触发点击事件后,新面板未在 Windows 表单上打开
New panel not opening on Windows Form after triggering click event
我有一个 Windows 表单应用程序。
我创建了一个扩展 Panel
的自定义 UserControl
。
在我的一个表单中,有一个按钮,单击该按钮会打开该面板。
但是,点击之后,我仍然没有看到表单上显示的面板。
表单代码
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 个面板,而设计器只是想把它们像俄罗斯套娃一样装箱。
所有 UI 控件都需要通过 Controls.Add() 方法拥有它们所属的父控件。
父级可以是 Form 或其他控件(并非所有控件都接受子级)。例如您的面板可以是文本框、组合框、标签等的父级。
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
如果您需要在添加控件后的某个阶段删除控件,那么您有两个选择。
- 创建一个单独的
List<BaseIngredientPanel>
来(也)存储您的
将它们添加到表单时进行控制。这个使用这个列表来查找
并通过 this.Controls.Remove()
方法 删除它们
- 在创建时为您的
BaseIngredientPanel
指定一个唯一的名称,并且
使用它通过查找和删除控件
this.Controls.Remove()
方法。所有控件都有一个名称 属性,因此您可以使用它。
如果要显示表单,class 应该派生自表单。您的 BaseIngredientPanel
不是表单,而是用户控件。
UserControl 类似于按钮、组合框、菜单、DataGridView 等其他控件。通常您使用 Visual Studio 设计器在窗体上显示它们。在极少数情况下,您可以通过编程方式执行此操作。
I created a custom UserControl which extends Panel.
你真正想要的是什么:
- 我想创建一种特殊的面板,它的行为类似于标准面板,只有很小的区别。我的 class 的用户可能会使用我的特殊面板的几乎所有属性:源自 class 面板
- 我想创建一种特殊的面板,其行为类似于标准面板。我想控制我的特殊面板的用户可以调用哪些方法:创建一个派生自 UserControl 的 class 并在其上放置一个面板。
- 我想创建一个窗体,我想在上面放置一个面板。这个面板有一些我只用在这个表单上的行为。
如果您想创建一种特殊的面板,可以在多个窗体上重复使用,请使用派生。您是从 Panel 还是 UserControl 派生取决于您希望 class 的万无一失,以及 class 的用户可以调用多少 Panel 方法。
如果你的特殊Panel只在一个Form上使用,就不用费心去创建特殊Panel了class。创建一个包含面板的窗体。
在特殊表格上使用标准面板
如果您决定不必重用此面板的行为,您可以将它放在一个新窗体上。使用 visual studio 设计器创建表单并在其上放置一个面板。订阅您要响应的面板事件。
如果您希望表单也有一个按钮,也可以使用 visual studio 设计器添加按钮并订阅事件 Button_Clicked。
要显示 PanelForm,您必须决定 PanelForm 是模型还是非模型。
- 模态:操作者只能使用这个表单,直到它被关闭。他不能使用此应用程序的其他形式。这是迄今为止最常用的一种表单:在菜单选择或单击按钮时:显示 PanelForm,使用 PanelForm,关闭 PanelForm,之后 parent 表单可以读取 PanelForm 的结果并采取相应行动.使用 Form.ShowDialog.
显示模态对话框
- 无模式:显示 PanelForm 时,操作员可以切换回 parent 表单并与之交互。这不经常使用。您可以使用它来显示有关 parent window 或应用程序状态的一些额外信息,例如鼠标的位置或您将绘制的选定形状。使用 Form.Show() 显示无模式对话框。请记住,在关闭 parent 表单之前,您必须关闭无模式对话框
显示模式
一个很好的例子是 OpenFileDialog 窗体
在您的 parent 表格中:
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;
您无法处置面板,因为它仍在使用中。面板在关闭时显示自行处置。
特别小组Class
如果您有一个特殊面板 Class(派生自 Panel 或 UserControl),则在编译后,面板控件会在 visual studio 设计器的工具箱中可见。
您应该使用 visual studio 设计器创建一个表单并将面板放在表单上:
class MyPanelForm : Form
{
public MyPanelForm()
{
InitializeComponent();
如果您使用visual studio设计器添加了特殊面板,那么您会在InitializeComponent
中找到它。您也可以在构造函数中自己添加它。在这种情况下,不要忘记将它添加到 this.components
,这样您的面板将在 MyPanelForm 被释放时被释放。
要显示 MyPanelForm,请使用 ShowDialog
或 Show
,如上一节所述。
我有一个 Windows 表单应用程序。
我创建了一个扩展 Panel
的自定义 UserControl
。
在我的一个表单中,有一个按钮,单击该按钮会打开该面板。
但是,点击之后,我仍然没有看到表单上显示的面板。
表单代码
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 个面板,而设计器只是想把它们像俄罗斯套娃一样装箱。
所有 UI 控件都需要通过 Controls.Add() 方法拥有它们所属的父控件。 父级可以是 Form 或其他控件(并非所有控件都接受子级)。例如您的面板可以是文本框、组合框、标签等的父级。
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
如果您需要在添加控件后的某个阶段删除控件,那么您有两个选择。
- 创建一个单独的
List<BaseIngredientPanel>
来(也)存储您的 将它们添加到表单时进行控制。这个使用这个列表来查找 并通过this.Controls.Remove()
方法 删除它们
- 在创建时为您的
BaseIngredientPanel
指定一个唯一的名称,并且 使用它通过查找和删除控件this.Controls.Remove()
方法。所有控件都有一个名称 属性,因此您可以使用它。
如果要显示表单,class 应该派生自表单。您的 BaseIngredientPanel
不是表单,而是用户控件。
UserControl 类似于按钮、组合框、菜单、DataGridView 等其他控件。通常您使用 Visual Studio 设计器在窗体上显示它们。在极少数情况下,您可以通过编程方式执行此操作。
I created a custom UserControl which extends Panel.
你真正想要的是什么:
- 我想创建一种特殊的面板,它的行为类似于标准面板,只有很小的区别。我的 class 的用户可能会使用我的特殊面板的几乎所有属性:源自 class 面板
- 我想创建一种特殊的面板,其行为类似于标准面板。我想控制我的特殊面板的用户可以调用哪些方法:创建一个派生自 UserControl 的 class 并在其上放置一个面板。
- 我想创建一个窗体,我想在上面放置一个面板。这个面板有一些我只用在这个表单上的行为。
如果您想创建一种特殊的面板,可以在多个窗体上重复使用,请使用派生。您是从 Panel 还是 UserControl 派生取决于您希望 class 的万无一失,以及 class 的用户可以调用多少 Panel 方法。
如果你的特殊Panel只在一个Form上使用,就不用费心去创建特殊Panel了class。创建一个包含面板的窗体。
在特殊表格上使用标准面板
如果您决定不必重用此面板的行为,您可以将它放在一个新窗体上。使用 visual studio 设计器创建表单并在其上放置一个面板。订阅您要响应的面板事件。
如果您希望表单也有一个按钮,也可以使用 visual studio 设计器添加按钮并订阅事件 Button_Clicked。
要显示 PanelForm,您必须决定 PanelForm 是模型还是非模型。
- 模态:操作者只能使用这个表单,直到它被关闭。他不能使用此应用程序的其他形式。这是迄今为止最常用的一种表单:在菜单选择或单击按钮时:显示 PanelForm,使用 PanelForm,关闭 PanelForm,之后 parent 表单可以读取 PanelForm 的结果并采取相应行动.使用 Form.ShowDialog. 显示模态对话框
- 无模式:显示 PanelForm 时,操作员可以切换回 parent 表单并与之交互。这不经常使用。您可以使用它来显示有关 parent window 或应用程序状态的一些额外信息,例如鼠标的位置或您将绘制的选定形状。使用 Form.Show() 显示无模式对话框。请记住,在关闭 parent 表单之前,您必须关闭无模式对话框
显示模式
一个很好的例子是 OpenFileDialog 窗体
在您的 parent 表格中:
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;
您无法处置面板,因为它仍在使用中。面板在关闭时显示自行处置。
特别小组Class
如果您有一个特殊面板 Class(派生自 Panel 或 UserControl),则在编译后,面板控件会在 visual studio 设计器的工具箱中可见。
您应该使用 visual studio 设计器创建一个表单并将面板放在表单上:
class MyPanelForm : Form
{
public MyPanelForm()
{
InitializeComponent();
如果您使用visual studio设计器添加了特殊面板,那么您会在InitializeComponent
中找到它。您也可以在构造函数中自己添加它。在这种情况下,不要忘记将它添加到 this.components
,这样您的面板将在 MyPanelForm 被释放时被释放。
要显示 MyPanelForm,请使用 ShowDialog
或 Show
,如上一节所述。