【问题标题】:Correct architecture to extend WinForm UserControl base classes?扩展 WinForm UserControl 基类的正确体系结构?
【发布时间】:2011-08-24 11:53:11
【问题描述】:

我有大量非常相似的用户控件。他们有很多共同的行为。我一直在使用具有通用内容的基类,然后根据需要专门化该类。

class BaseControl : UserControl 
{
   // common
}  

class RedControl : BaseControl
{
   // specialized
}

class BlueControl : BaseControl
{
   // specialized
}

等等……

在我需要开始插入或更改 BaseControl 中包含的子控件的布局之前,此方法效果很好。例如,RedControl 需要将 Button 添加到基本控件的特定面板。在其他情况下,我需要更改其他基本子控件的大小或布局。

当我尝试以下代码时,在运行时我没有看到任何按钮...

public partial class RedControl : BaseControl
{
  public RedControl()
  {
    InitializeComponent();

    addButtonToBase();  // no button shows up 
    this.PerformLayout();
  }
  void addButtonToBase()
  {
    Button button  = new Button();
    button.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
    button.Location = new System.Drawing.Point(3, 3);
    button.Size = new System.Drawing.Size(23, 23);
    button.Text = "My Button";

    baseSplitContainer.Panel1.Controls.Add(button); // protected child control in base
  }
  // ...
}

如果我将 addButtonToBase() 设为虚拟并手动将其添加到 BaseControl 的 InitalizeComponent() 中生成的代码中,我 可以 使按钮显示为 baseSplitContainer 的子项。 BaseControl 的布局仍在进行中,您可以在 C#.Net 的构造函数中调用虚函数....

所以即使它有效,它也不是一个好的解决方案。一方面,当我在 VS 设计器中编辑 BaseControl 时,在 IntializeComponent 中对 addBaseControl() 的调用被删除, 对于另一个在构造函数中调用虚函数感觉很危险。

我想我需要让基本控件的布局在派生控件中再次发生... 我试过了,但要么做错了,要么不起作用......

顺便说一句,是的,我知道 WPF 擅长这一点。由于其他系统的限制,无法使用它。

【问题讨论】:

    标签: c# winforms user-controls dynamic-usercontrols


    【解决方案1】:

    事实证明,修改基本控件布局的正确方法是覆盖来自 Control.OnLayout() 的布局调用

    有点像

    public RedControl()
    {
        //....
        protected override void OnLayout(LayoutEventArgs e)
        {
            addButtonToBase(); // modify base layout
            base.OnLayout(e);
        }
    }
    

    【讨论】:

      【解决方案2】:

      我认为您只是错过了一些调用基本初始化逻辑来创建控件的内容,然后您的更改将被覆盖。试着这样称呼它

      public RedControl()
      : base()
        { ... }
      

      public RedControl()
        {
          base.InitializeComponent();
          InitializeComponent();
      
          addButtonToBase();  // no button shows up 
          this.PerformLayout();
        }
      

      【讨论】:

      • 当派生控件被构造时,基类构造函数总是被调用。不需要调用 base.InitializeComponent() 也没有解决布局问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多