WinForms - UserControl - List<一个Collection< bool>作为UserContr

本文关键字:UserContr bool 作为 一个 UserControl List WinForms Collection | 更新日期: 2023-09-27 18:08:10

为什么MessageBox和CheckBox在更改第一个属性的值时出现在设计时,而在向第二个添加项时不出现?

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

这是相同的场景,当我改变集合列表…值被保留(或在第二种情况下添加到集合),设计器为InitializeComponent()生成代码。

在@taffer answer后编辑

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

现在的问题是:当我在编辑器中添加第三个项目时,它只绘制一个复选框,但应该绘制3个复选框…此外,在调试中,我看到foreach循环进行了3次:第一次收集有1项,第二次收集有2项,第三次收集有3项,但最后我在_checkboxPanel中只看到一个复选框。

WinForms - UserControl - List<一个Collection< bool>作为UserContr

因为只有在替换整个集合时才会执行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);
    }
}

您现在使用的内置集合编辑器只更改集合对象的内容。它工作得很好,但根本不会调用setter。换句话说,它从不创建新的集合对象,也不知道如何创建。

要调用属性设置器,您必须创建自己的UITypeEditor,并让它从其EditValue()方法覆盖返回一个新集合。很容易做到,首先添加一个对System的引用。设计,然后使你的代码看起来像这样:

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,这样所有这些工具都更容易解释