2010-04-22 33 views
16

Tôi đang thiết kế một điều khiển giãn nở đơn giản.Kiểm soát người dùng dưới dạng vùng chứa tại thời điểm thiết kế

Tôi đã bắt nguồn từ UserControl, các điều khiển bên trong được vẽ, được xây dựng, chạy; tất cả ok.

Vì Bộ điều khiển bên trong là Bảng điều khiển, tôi muốn sử dụng nó làm vùng chứa tại thời điểm thiết kế. Thực tế tôi đã sử dụng các thuộc tính:

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

Tuyệt vời tôi nói. Nhưng nó không phải là ...

Kết quả là tôi có thể sử dụng nó như container tại thời gian thiết kế nhưng:

  • Các điều khiển bổ sung trở lại các điều khiển bên trong đã được nhúng trong điều khiển người dùng
  • Thậm chí nếu tôi đẩy đầu một điều khiển thêm vào thời gian thiết kế, khi chạy nó là trở lại một lần nữa trên điều khiển nhúng để người dùng điều khiển
  • tôi không thể hạn chế khu vực container tại thời gian thiết kế thành một khu vực Bảng điều chỉnh

Tôi đang thiếu gì? Đây là mã để hoàn thành ... tại sao đoạn mã này không hoạt động?

[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; 
     } 
    } 
} 

tôi đã tìm thấy nhiều tài nguyên (Interaction, designed, limited area), nhưng không có gì là hữu ích cho việc phẫu ...

Trên thực tế có một trick, vì System.Windows.Forms lớp có thể được thiết kế (như thường lệ) và có một hành vi đúng lúc chạy (ví dụ như TabControl).

Trả lời

16

ParentControlDesigner không biết bạn muốn làm gì. Nó chỉ biết bạn muốn UserControl của bạn là một container.

Những gì bạn cần làm là thực hiện thiết kế của riêng bạn mà cho phép chế độ thiết kế trên bảng điều khiển:

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"); 
       } 
      } 
     } 
    } 

Tôi học được điều này từ Henry Minute trên CodeProject. Xem liên kết để biết một số cải tiến về kỹ thuật.

+0

Nó hoạt động ! Nhưng thực ra nó không có những khiếm khuyết sau: bạn có thể di chuyển/kích thước "WorkingArea" (sự khác biệt nào có "DropZone"?) nhưng trong thời gian chạy nó không được phản ánh; các điều khiển dopped tại thời gian thiết kế không thể được liên kết trên giới hạn container. – Luca

+0

Tôi đang gặp hai vấn đề tương tự và tự hỏi làm cách nào để sửa lỗi – Telanor

+0

Tắt đầu tôi không chắc chắn cách xử lý các vấn đề đó. Bạn đã xem liên kết chưa? Anh ta có thể đã giải quyết những điều đó bằng phiên bản nâng cao của mình. http://www.codeproject.com/KB/miscctrl/NestedControlDesigner.aspx –

2

Ngoài câu trả lời ở trên. Nó được đề cập trong các ý kiến, rằng người dùng có thể kéo WorkingArea. Sửa chữa của tôi cho điều đó là bao gồm bảng điều khiển WorkingArea trong một bảng điều khiển khác, đặt nó vào Dock.Fill. Để không cho phép người dùng thay đổi lại, tôi đã tạo một lớp ContentPanel ghi đè và ẩn thuộc tính Dock:

Đối với tôi, điều này làm cho nó đủ an toàn. Chúng tôi chỉ sử dụng sự kiểm soát nội bộ, vì vậy chúng tôi chủ yếu muốn ngăn chặn các nhà phát triển vô tình kéo những thứ xung quanh. Có những cách chắc chắn để mess nó lên anyway.

3

Để ngăn chặn các khu vực làm việc kể từ khi được chuyển/thay đổi kích cỡ trong thiết kế bạn phải tạo ra một lớp cho rằng khu vực làm việc mà giấu đi những địa điểm, Height, Width, tính Kích từ nhà thiết kế:

public class WorkingArea : Panel 
{ 
    [Browsable(false)] 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    public new Point Location 
    { 
     get 
     { 
      return base.Location; 
     } 
     set 
     { 
      base.Location = value; 
     } 
    } 
... 
} 
Các vấn đề liên quan