简体   繁体   English

使用C#保护用户自己的控件的控件集合

[英]Protect the Controls collection of my own control from users in C#

Good day. 美好的一天。 I create my control that contains group of another UserControls, for example: 我创建了包含另一个UserControls组的控件,例如:

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

在此处输入图片说明

It is all right, but the users of MySuperControl have access to Controls property and can change Location of small controls and even remove their from collection! 没关系,但是MySuperControl的用户可以访问Controls属性,并且可以更改小型控件的位置,甚至可以将其从集合中删除! Encapsulation is broken! 封装坏了! Example of user's bad actions: 用户的不良行为示例:

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

or 要么

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

This will result to crash MySuperControl: 这将导致MySuperControl崩溃:

在此处输入图片说明

How to protect inner controls of MySuperControl? 如何保护MySuperControl的内部控件? Thanks. 谢谢。

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

This is the best you can get from this situation. 在这种情况下,这是最好的选择。 You can access the controls collection by calling base.Controls. 您可以通过调用base.Controls访问控件集合。 If someone is smart enough, however to cast your MyUserControl to UserControl he will be able to modify the collection but there is nothing you can do about that. 如果某人足够聪明,但是可以将MyUserControl转换为UserControl,他将能够修改集合,但是您无能为力。

I came up with this solution: 我想出了这个解决方案:

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

Users can still access to Control.Controls property by cast MyUserControl to Control: 用户仍然可以通过将MyUserControl强制转换为Control来访问Control.Controls属性:

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

But if they use c.Controls instead, all will work normally. 但是,如果他们改用c.Controls,则所有功能都将正常运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM