Вот вспомогательный класс, в который вы можете передать Form и Control Type, и он соединит все соответствующие элементы управления. В этом примере все кнопки подключены, поэтому вы можете перетаскивать их. Просто измените «Button» на интересующий вас тип управления:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.WireControlsOfType<Button>();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
f2.WireControlsOfType<Button>();
}
}
Вспомогательный класс в другом файле:
public static class FormHelper
{
public static void WireUserControl(this UserControl uc)
{
uc.MouseDown += _MouseDown;
uc.MouseMove += _MouseMove;
uc.MouseUp += _MouseUp;
}
public static void WireControlsOfType<T>(this Control sourceControl)
{
foreach(var ctl in sourceControl.RecursiveFindControlsByType<T>())
{
ctl.MouseDown += _MouseDown;
ctl.MouseMove += _MouseMove;
ctl.MouseUp += _MouseUp;
}
}
// Code by Jon Skeet: https://stackoverflow.com/a/2055946/2330053
public static IEnumerable<Control> RecursiveFindControlsByType<T>(this Control control)
{
foreach (Control c in control.Controls)
{
if (c is T)
{
yield return c;
}
if (c.Controls.Count > 0)
{
foreach (Control ctl in c.RecursiveFindControlsByType<T>())
{
yield return ctl;
}
}
}
}
private static bool mouseDown;
private static Point lastLocation;
private static void _MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
lastLocation = e.Location;
}
private static void _MouseMove(object sender, MouseEventArgs e)
{
Control source = (Control)sender;
if (mouseDown)
{
source.Location = new Point((source.Location.X - lastLocation.X) + e.X, (source.Location.Y - lastLocation.Y) + e.Y);
}
}
private static void _MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
}
Обратите внимание, что я связываю Form1 в событии Load () с "this", но я также демонстрирую это для нового экземпляра Form2 в обработчике Click ().
Дополнительное сообщение на основе вопросов комментариев
Основываясь на ваших комментариях, вот пример, показывающий, что кнопки внутри UserControl подключены, чтобы позволить им перемещаться. (Я изменил метод WireControlsOfType<>
для принятия универсального элемента управления вместо формы.) В свойствах UserControl по умолчанию ничего не изменилось, чтобы разрешить это:
private void button1_Click(object sender, EventArgs e)
{
panel1.Controls.Clear();
UserControlA ucA = new UserControlA();
ucA.Dock = DockStyle.Fill;
panel1.Controls.Add(ucA);
ucA.WireControlsOfType<Button>();
}
Статический класс FormHelper - это то, что позволяет эту магию. Это может быть собственный класс, и его не нужно копировать / связывать ни с одним из Forms / UserControls; фактически он не зависит от них и может находиться в отдельном файле.
Если вы хотите, чтобы весь UserControl мог перетаскиваться вокруг своего контейнера, я добавил другой вспомогательный метод с именем WireUserControl()
к вспомогательному классу выше. Таким образом, фрагмент ниже добавляет несколько экземпляров UserControlA на panel1, и каждый из них можно перетаскивать отдельно:
private void button1_Click(object sender, EventArgs e)
{
UserControlA ucA = new UserControlA();
panel1.Controls.Add(ucA);
ucA.WireUserControl();
}