2010-04-22 6 views
16

Я разрабатываю простой элемент управления расширителя.Контроль пользователя как контейнер во время разработки

Я получил от UserControl, нарисовал внутренние элементы управления, построил, запустил; все нормально.

Поскольку внутренний элемент управления представляет собой панель, я бы хотел использовать ее в качестве контейнера во время разработки. Действительно, я использовал следующие атрибуты:

[Designer(typeof(ExpanderControlDesigner))] 
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] 

Отлично, я говорю. Но это не так ...

В результате я могу использовать его в качестве контейнера во время разработки, но:

  • Добавленные управления вернуться внутренние элементы управления уже встроены в пользовательский элемент управления
  • Даже если я нажимаю к началу контроль добавляемые во время разработки, во время выполнения это снова на управлении, внедренное в пользовательском элементе управления
  • Я не могу ограничить область контейнера во время разработки в область панели

Что мне не хватает? Вот код для полноты ... почему этот фрагмент кода не работает?

[Designer(typeof(ExpanderControlDesigner))] 
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] 
public partial class ExpanderControl : UserControl 
{ 
    public ExpanderControl() 
    { 
     InitializeComponent(); 
.... 

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
internal class ExpanderControlDesigner : ControlDesigner 
{ 
    private ExpanderControl MyControl; 

    public override void Initialize(IComponent component) 
    { 
     base.Initialize(component); 

     MyControl = (ExpanderControl)component; 

     // Hook up events 
     ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService)); 
     IComponentChangeService c = (IComponentChangeService)GetService(typeof(IComponentChangeService)); 

     s.SelectionChanged += new EventHandler(OnSelectionChanged); 
     c.ComponentRemoving += new ComponentEventHandler(OnComponentRemoving); 
    } 

    private void OnSelectionChanged(object sender, System.EventArgs e) 
    { 

    } 

    private void OnComponentRemoving(object sender, ComponentEventArgs e) 
    { 

    } 

    protected override void Dispose(bool disposing) 
    { 
     ISelectionService s = (ISelectionService)GetService(typeof(ISelectionService)); 
     IComponentChangeService c = (IComponentChangeService)GetService(typeof(IComponentChangeService)); 

     // Unhook events 
     s.SelectionChanged -= new EventHandler(OnSelectionChanged); 
     c.ComponentRemoving -= new ComponentEventHandler(OnComponentRemoving); 

     base.Dispose(disposing); 
    } 

    public override System.ComponentModel.Design.DesignerVerbCollection Verbs 
    { 
     get 
     { 
      DesignerVerbCollection v = new DesignerVerbCollection(); 

      v.Add(new DesignerVerb("&asd", new EventHandler(null))); 

      return v; 
     } 
    } 
} 

я нашел много ресурсов (Interaction, designed, limited area), но ничего не было полезны для тех оперативных ...

На самом деле есть трюк, так как System.Windows.Forms классы могут (как обычно) и иметь правильное поведение во время выполнения (например, TabControl).

ответ

16

ParentControlDesigner не знает, чего вы хотите. Он знает, что вы хотите, чтобы ваш UserControl был контейнером.

Что вам нужно сделать, это реализовать свой собственный конструктор, который позволяет режим проектирования на панели:

using System.ComponentModel; 
    using System.Windows.Forms; 
    using System.Windows.Forms.Design; 

    namespace MyCtrlLib 
    { 
     // specify my custom designer 
     [Designer(typeof(MyCtrlLib.UserControlDesigner))] 
     public partial class UserControl1 : UserControl 
     { 
      public UserControl1() 
      { 
       InitializeComponent(); 
      } 

      // define a property called "DropZone" 
      [Category("Appearance")] 
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
      public Panel DropZone 
      { 
       get { return panel1; } 
      } 
     } 

     // my designer 
     public class UserControlDesigner : ParentControlDesigner 
     { 
      public override void Initialize(System.ComponentModel.IComponent component) 
      { 
       base.Initialize(component); 

       if (this.Control is UserControl1) 
       { 
        this.EnableDesignMode(
         (UserControl1)this.Control).DropZone, "DropZone"); 
       } 
      } 
     } 
    } 

Я узнал это от Henry Minute на CodeProject. См. Ссылку на некоторые улучшения в технике.

+0

Он работает ! Но на самом деле он не имеет следующих недостатков: вы можете перемещать/изменять размер «WorkingArea» (какие различия имеют «DropZone»?), но во время выполнения это не отражается; доппированные элементы управления во время разработки не могут быть выровнены по границам контейнера. – Luca

+0

У меня такие же 2 проблемы и интересно, как это можно исправить – Telanor

+0

Сверху моей головы Я не уверен, как справиться с этими проблемами. Вы посмотрели ссылку? Возможно, он решил их с расширенной версией. http://www.codeproject.com/KB/miscctrl/NestedControlDesigner.aspx –

2

В дополнение к ответу выше. В комментариях упоминается, что пользователь может перетащить WorkArea. Мое исправление заключается в том, чтобы включить панель WorkingArea в другую панель, установив ее в Dock.Fill. Чтобы запретить пользователю изменять его обратно, я создал класс ContentPanel, который переопределяет и скрывает свойство Dock:

class ContentPanel : Panel 
{ 
    [Browsable(false)] 
    public override DockStyle Dock 
    { 
     get { return base.Dock; } 
     set { base.Dock = DockStyle.Fill; } 
    } 
} 

Для меня, это делает его достаточно безопасным. Мы используем только внутренний контроль, поэтому мы в основном хотим предотвратить случайное перетаскивание разработчиков. Конечно, есть способы все испортить.

3

Чтобы предотвратить рабочую зону от перемещаются/изменения размера в конструкторе вы должны создать класс для этой рабочей области, скрывающей Расположение, высота, ширина, свойства Размер от дизайнера:

public class WorkingArea : Panel 
{ 
    [Browsable(false)] 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    public new Point Location 
    { 
     get 
     { 
      return base.Location; 
     } 
     set 
     { 
      base.Location = value; 
     } 
    } 
... 
} 
Смежные вопросы