WinForms - UserControl - 列出<bool>集合<bool>作为UserControl的可浏览属性

时间:2015-08-17 08:31:52

标签: c# winforms user-controls propertygrid design-time

为什么MessageBox和CheckBox在更改First属性的值时会在Design-Time中出现,而在将项目添加到Second时却不会出现?

    private string _first;
    [Description(""), Category("GostcompSettings"), DefaultValue("27017")]
    public string First
    {
        get { return __first; }
        set
        {

            _searchAreasChceckBoxList.Clear();
            pPanelWithCheckboxies.Controls.Clear();
            int x = 10;
            int y = 10;

            CheckBox _tempCheck = new CheckBox();
            _tempCheck.Checked = true;
            _tempCheck.Location = new Point(x, y);

            _searchAreasChceckBoxList.Add(_tempCheck);
            pPanelWithCheckboxies.Controls.Add(_tempCheck);

            MessageBox.Show("zmiana");
            _first = value;
        }
    }


    private Collection<bool> _second= new Collection<bool>();
    [Description(""), Category("*")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Collection<bool> Second
    {
        get
        {
            return _second;
        }
        set
        {

            _searchAreasChceckBoxList.Clear();
            pPanelWithCheckboxies.Controls.Clear();
            int x = 10;
            int y = 10;

            CheckBox _tempCheck = new CheckBox();
            _tempCheck.Checked = true;
            _tempCheck.Location = new Point(x, y);

            _searchAreasChceckBoxList.Add(_tempCheck);
            pPanelWithCheckboxies.Controls.Add(_tempCheck);

            MessageBox.Show("*");
            _second= value;
        }
    }

当我将Collection更改为List时,情况相同... 保留值(或在第二种情况下添加到Collection),设计器为InitializeComponent()生成代码。

在@taffer answear之后编辑

public class SearchAreaInfo
{
    public SearchAreasEnum searchArea
    {
        get; set;
    }
}

public class SearchAreaInfoCollection : Collection<SearchAreaInfo>
{
    private Panel _checkboxParent;

    public SearchAreaInfoCollection(Panel checkboxParent) : base()
    {
        _checkboxParent = checkboxParent;
    }

    // called on Add/Insert
    protected override void InsertItem(int index, SearchAreaInfo item)
    {
        base.InsertItem(index, item);
        RepaintChackboxPanel();
    }

    // called on Remove/RemoveAt
    protected override void RemoveItem(int index)
    {
        base.RemoveItem(index);
        RepaintChackboxPanel();
    }

    // called when an element is set by the indexer
    protected override void SetItem(int index, SearchAreaInfo item)
    {
        base.SetItem(index, item);
        RepaintChackboxPanel();
    }

    private void RepaintChackboxPanel()
    {
        //_searchAreasChceckBoxList.Clear();
        _checkboxParent.Controls.Clear();
        int x = 0;
        int y = 0;

        foreach (var item in this)
        {
            CheckBox _tempCheck = new CheckBox();
            _tempCheck.Checked = true;
            _tempCheck.Location = new Point(x, y);
            _tempCheck.BringToFront();

            //_searchAreasChceckBoxList.Add(_tempCheck);
            _checkboxParent.Controls.Add(_tempCheck);                
            x += 5;
            y += 5;
        }
        _checkboxParent.Invalidate();
    }
}

    private SearchAreaInfoCollection _searchAreas;
    [Description(""), Category("GostcompSettings")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SearchAreaInfoCollection SearchAreas
    {
        get
        {
            return _searchAreas;
        }
    }

现在的问题是:当我在编辑器中添加let&#39; s说第三项时,它只绘制一个复选框,但应绘制3个复选框... 此外,在调试中,我看到foreach循环经过3次:第一次收集有1个项目,第二次收集有2个项目,第三次收集有3个项目,但最后我只看到_checkboxPanel中的一个复选框。

2 个答案:

答案 0 :(得分:1)

因为只有在替换整个集合时才会执行Second属性的setter。添加/删除项目时,getter会返回您的集合实例(_second),并在该对象实例上调用Add / Remove方法。

如果要对元素添加/删除执行检查,请改为创建自定义集合类型:

public class MyBoolCollection: Collection<bool>
{
    // called on Add/Insert
    protected override void InsertItem(int index, bool item)
    {
        // do some checks here
        base.InsertItem(index, item);
    }

    // called on Remove/RemoveAt
    protected override void RemoveItem(int index)
    {
        // do some checks here
        base.RemoveItem(index, item);
    }

    // called when an element is set by the indexer
    protected override void SetItem(int index, bool item)
    {
        // do some checks here
        base.SetItem(index, item);
    }
}

答案 1 :(得分:1)

您现在使用的内置集合编辑器仅更改集合对象的内容。哪个工作正常,但根本没有调用你的二传手。换句话说,它从不创建新的集合对象,也不知道如何做到这一点。

要调用属性setter,必须创建自己的UITypeEditor并让它从EditValue()方法重写返回一个新集合。很容易做到,首先添加对System.Design的引用,然后使代码看起来类似于:

using System.Drawing.Design;
...
        [Editor(typeof(MyEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public Collection<bool> Second {
            // etc...
        }

        private class MyEditor : UITypeEditor {
            public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
                return UITypeEditorEditStyle.Modal;
            }
            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
                var editor = new System.ComponentModel.Design.CollectionEditor(typeof(Collection<bool>));
                var retval = (Collection<bool>)editor.EditValue(context, provider, value);
                return new Collection<bool>(retval);

            }
        }

您可能希望稍微改进一下,比如实现自己的编辑器UI,这样所有这些bool都更容易理解。