2014-02-19 3 views
1

좋은 하루.C에서 사용자가 내 컨트롤의 컨트롤 컬렉션을 보호합니다.

public class MySuperControl : Control 
{ 
    private List<MySmallControl> _smallControls; 

    public MySuperControl() 
    { 
     //_smallControls = ... //creating of small controls 
     this.Controls.AddRange(_smallControls); 
    } 

    class MySmallControl : UserControl 
    { 
     //contains button and checkbox 
    } 
} 

enter image description here

그것은 모든 권리이지만, MySuperControl의 사용자 컨트롤 속성에 액세스 할 수있는 작은 컨트롤의 위치를 ​​변경할 수 있습니다, 심지어 : 나는 예를 들어, 다른 추가 된 UserControls의 그룹을 포함하는 내 컨트롤을 만들 컬렉션에서 삭제하십시오! 캡슐화가 깨졌습니다! 사용자의 나쁜 행동의 예 :

enter image description here

방법 MySuperControl의 내부 컨트롤을 보호하기 위해 :

MySuperControl c=new MySuperControl(); 
c.Controls.Clear(); 

또는

MySuperControl c=new MySuperControl(); 
foreach (Control smallControl in c.Controls) 
{ 
    smallControl.Location = new Point(999, 999); 
} 

이 MySuperControl를 충돌이 발생할 것인가? 감사.

답변

1
public class MyUserControl : UserControl 
{ 
    public new Control.ControlCollection Controls 
    { 
     get { throw new NotSupportedException(); } 
    } 
} 

이 상황에서 얻을 수있는 최선의 방법입니다. base.Controls를 호출하여 컨트롤 컬렉션에 액세스 할 수 있습니다. 누군가가 충분히 똑똑하다하더라도 MyUserControl을 UserControl에 캐스팅하면 콜렉션을 수정할 수는 있지만 그렇게 할 수있는 방법은 없습니다.

0

나는이 솔루션을 내놓았다 :

public class MySuperControl : Control 
{ 
    private List<MySmallControl> _smallControls; 

    public MySuperControl() 
    { 
     Controls = new CControlCollection(this); 
     //_smallControls = ... //creating of small controls 
     ((Control)this).Controls.AddRange(_smallControls); 
    } 

    class MySmallControl : UserControl 
    { 
     //contains button and checkbox 
    } 

    //Wrapper for the Control.Controls property of the MySuperControl 
    public new CControlCollection Controls { get; private set; } 

    public class CControlCollection : ICollection<Control> 
    { 
     private Collection<Control> items; 
     private MySuperControl parent; 

     public CControlCollection(MySuperControl parent) 
     { 
      items = new Collection<Control>(); 
      this.parent = parent; 
     } 

     public int Count 
     { 
      get { return items.Count; } 
     } 

     public bool IsReadOnly 
     { 
      get { return false; } 
     } 

     public void Add(Control item) 
     { 
      items.Add(item); 
      ((Control)parent).Controls.Add(item); 
     } 

     public void AddRange(Control[] itemsArray) 
     { 
      foreach (Control item in itemsArray) 
      { 
       items.Add(item); 
       ((Control)parent).Controls.Add(item); 
      } 
     } 

     public void Clear() 
     { 
      foreach (Control c in items) 
      { 
       ((Control)parent).Controls.Remove(c); 
      } 
      items.Clear(); 
     } 

     public bool Contains(Control item) 
     { 
      return items.Contains(item); 
     } 

     public void CopyTo(Control[] array, int arrayIndex) 
     { 
      items.CopyTo(array, arrayIndex); 
     } 

     public bool Remove(Control item) 
     { 
      ((Control)parent).Controls.Remove(item); 
      return items.Remove(item); 
     } 

     public IEnumerator<Control> GetEnumerator() 
     { 
      return items.GetEnumerator(); 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      return items.GetEnumerator(); 
     } 
    } 
} 

사용자는 여전히 제어하는 ​​캐스팅을 MyUserControl로 Control.Controls 속성에 액세스 할 수 있습니다

MySuperControl c=new MySuperControl(); 
((Control)c).Controls.Clear(); 

을하지만 대신 c.Controls를 사용하는 경우, 모든 정상적으로 작동합니다.

+0

그러나이 방법은 하위 컨트롤의 Control.Parent 속성을 변경하거나 PropertyGrid를 통해 ControlCollection에 액세스하는 것으로 간주되지 않습니다. 너무 많은 문제 ... 예를 들어, MySuperControl.Controls_2 속성을 사용하는 것이 훨씬 더 좋지만 구현 방법을 모르겠습니다. – Feofilakt