C#:将派生类作为一个通用参数传递

AAS*_*S.N 3 c# oop winforms

我最近开始学习更多关于事件/代理以及类扩展的知识.

我想通过向Windows Form控件中添加一个扩展方法将我学到的东西付诸实践SetDraggable(),后者又使用a MouseDownMouseMove事件来移动控件.

一切正常,除了它只适用于特定控件 - 在我的情况下,a Button.

namespace Form_Extensions
{
    public static class Extensions
    {
        private static System.Windows.Forms.Button StubButton;
        private static Point MouseDownLocation;
        public static void SetDraggable(this System.Windows.Forms.Button b)
        {
            b.MouseDown += b_MouseDown;
            b.MouseMove += b_MouseMove;
            StubButton = b;
        }

        private static void b_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                MouseDownLocation = e.Location;
            }
        }

        static void b_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                StubButton.Left = e.X + StubButton.Left - MouseDownLocation.X;
                StubButton.Top = e.Y + StubButton.Top - MouseDownLocation.Y;
            }
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

可以看出,我需要特定的控件才能调用Mouse事件 - 我无法从类访问这些事件System.Windows.Forms.

所以我的问题仍然存在 - 是否有一个概念允许程序员一般将所有派生类作为参数传递.我基本上试图避免复制粘贴每个控件的下面的代码,并希望将其推广到所有派生的类System.Windows.Forms.

据我所知,这个想法的主要缺陷是我假设所有派生类都有我需要的事件; 但是,由于代表形式的功能存在类似的事情,我希望有人可以权衡涉及对象或参数的情况.

Lua*_*aan 6

父类不是System.Windows.Forms,那只是命名空间.实际的父类是Control,你当然可以使用:)使用泛型方法也是可能的,但不是真的必要.

理想情况下,您还希望避免使用这些静态字段,因为它可能具有多个并发可拖动字段; SetControlDraggable方法中的闭包会更好用:

public static void SetControlDraggable(this Control control)
{
  Point mouseDownLocation = Point.Empty;

  control.MouseDown += (s, e) =>
    {
      if (e.Button == MouseButtons.Left) mouseDownLocation = e.Location;
    }
  control.MouseUp += (s, e) =>
    {
      if (e.Button == MouseButtons.Left)
      {
        control.Left = e.X + control.Left - mouseDownLocation.X;
        control.Top = e.Y + control.Top - mouseDownLocation.Y;
      }
    }
}
Run Code Online (Sandbox Code Playgroud)