C# Windows Forms中如何将用户控件内的面板移至另一用户控件
Hey there! Let's break down how to get that product panel from your menu UserControl over to the See order one when the "Order now" button is clicked. This is a common scenario with WinForms UserControls, and we can solve it using custom events to pass data between the controls cleanly.
Step 1: Add a Custom Event to Your menu UserControl
Since UserControls can't directly access each other's internal controls, we'll create a custom event in the menu control to notify the main form when a panel is ready to be moved.
Add this code to your menu UserControl class:
// Define a custom event to pass the selected product panel public event EventHandler<ProductPanelEventArgs> PanelOrdered; // Custom event args to carry the panel we want to move public class ProductPanelEventArgs : EventArgs { public Panel TargetPanel { get; } public ProductPanelEventArgs(Panel panel) { TargetPanel = panel; } } // Click handler for your "Order now" buttons private void OrderNowButton_Click(object sender, EventArgs e) { // Get the button that was clicked, then find its parent panel Button clickedBtn = sender as Button; Panel productPanel = clickedBtn.Parent as Panel; // Trigger the event to send the panel to the main form PanelOrdered?.Invoke(this, new ProductPanelEventArgs(productPanel)); }
Don't forget to bind each "Order now" button's
Clickevent to thisOrderNowButton_Clickmethod—you can do this in the WinForms designer, or dynamically if you're generating panels programmatically.
Step 2: Subscribe to the Event in Your Main Form
Now, your main form will listen for the event from the menu control, then move (or copy) the panel to the See order control.
Add this code to your main form class:
public MainForm() { InitializeComponent(); // Subscribe to the PanelOrdered event from your menu UserControl menuUserControl.PanelOrdered += OnPanelOrdered; } private void OnPanelOrdered(object sender, menu.ProductPanelEventArgs e) { // Option 1: Move the original panel from menu to See order // Remove the panel from the menu control first e.TargetPanel.Parent.Controls.Remove(e.TargetPanel); // Add it to the See order control seeOrderUserControl.Controls.Add(e.TargetPanel); // Adjust layout (example: dock to top so panels stack neatly) e.TargetPanel.Dock = DockStyle.Top; // Option 2: Copy the panel instead of moving it (keep original in menu) // Panel clonedPanel = CloneProductPanel(e.TargetPanel); // seeOrderUserControl.Controls.Add(clonedPanel); // clonedPanel.Dock = DockStyle.Top; }
Step 3: (Optional) Clone the Panel Instead of Moving It
If you want to keep the original panel in the menu control while adding a copy to See order, use this helper method to clone the panel and its contents:
private Panel CloneProductPanel(Panel originalPanel) { Panel clonedPanel = new Panel { Size = originalPanel.Size, BackColor = originalPanel.BackColor, Padding = originalPanel.Padding }; // Copy all controls from the original panel to the clone foreach (Control ctrl in originalPanel.Controls) { Control clonedCtrl = (Control)Activator.CreateInstance(ctrl.GetType()); clonedCtrl.Location = ctrl.Location; clonedCtrl.Size = ctrl.Size; clonedCtrl.Text = ctrl.Text; clonedCtrl.Font = ctrl.Font; // Handle special controls like PictureBoxes if (ctrl is PictureBox originalPb) { PictureBox clonedPb = clonedCtrl as PictureBox; clonedPb.Image = originalPb.Image; clonedPb.SizeMode = originalPb.SizeMode; } clonedPanel.Controls.Add(clonedCtrl); } return clonedPanel; }
That's it! This approach keeps your UserControls decoupled (they don't need to know about each other directly) and follows good WinForms practices. Test it out—clicking "Order now" should move your product panel over to the See order control like you want.
内容的提问来源于stack exchange,提问作者Hremaliuc Andrei Ciprian

