【问题标题】:Add sub controls to custom control after click the "OK" button of the "CollectionEditor" window in design time在设计时单击“CollectionEditor”窗口的“确定”按钮后将子控件添加到自定义控件
【发布时间】:2012-11-21 13:09:22
【问题描述】:

我已经创建了我的自定义控件。它有一个名为“Tab”的属性。此属性将从“DockContainerItem”类继承的“FloorsInformation”控件集合添加到我的自定义控件中。

现在,我想在单击选项卡“CollectionEditor”窗口的“确定”按钮后将“FloorsInformation”控件添加到我的自定义控件中。

我有这样做的“AddTabs”方法。但是,我不能在正确的地方调用它。我必须在“Tab”属性的“set accessor”中调用“AddTabs”方法,但它永远不会发生。

我也可以从“Tab”属性的“get accessor”中调用这个方法,但是在“Tab”属性的“get accessor”中调用这个方法会报错,因为程序访问“get” “Tab”属性的访问器”。

[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
[ToolboxItem(true), ToolboxBitmap(typeof(ToolboxIconResourceFinder), "FloorsGrouping.bmp")]
[DisplayName("Floors Group")]
[Editor("WindowsFormsControlLibrary2.FloorsGrouping, WindowsFormsControlLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=197889249da45bfc", typeof(UITypeEditor))]
[Description("Floorssssssss")]
[Category("Saino")]
[DefaultProperty("Text")]
[DesignerCategory("Component")] //Form //Designer //Empty String ("")
public partial class FloorsGrouping : Bar
{
    private Tabs tabs = new Tabs();

    public FloorsGrouping()
    {
        InitializeComponent();
        this.AutoHide = true;
    }

    [Category("Data")]
    [DisplayName("Tabs")]
    [Description("Tabsssssssssssss")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Editor(typeof(ItemsCollectionEditor), typeof(UITypeEditor))]
    public Tabs Tab
    {
        get
        {
            //AddTabs();
            return tabs;
        }
        //set
        //{
            //AddTabs();
        //}
    }

    public void AddTabs()
    {
        foreach (DockContainerItem dciItem in Tab)
        {
            if (!Parent.Controls.ContainsKey(dciItem.Name))
            {
                Items.Add(dciItem);
            }
        }
    }
}

[DisplayName("Floors Information")]
[Description("Floors Informationnnnnnnnnnnnnnnn")]
[DefaultProperty("Text")]
[DesignerCategory("Component")]
[ToolboxItem(false)]
public class FloorsInformation : DockContainerItem
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    private SimilarFloorsInformation similarFloorsInformation = new SimilarFloorsInformation();
    private AllFloorsInformation allFloorsInformation = new AllFloorsInformation();
    private string text = "Floors Information";

    public FloorsInformation()
    {

    }

    [Category("Data")]
    [DisplayName("Similar Floors Panel")]
    [Description("Similar Floors Panellllllllllllllllllll")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public SimilarFloorsInformation SimilarFloorsInfo
    {
        get
        {
            return similarFloorsInformation;
        }
        set
        {
            similarFloorsInformation = value;
        }
    }

    [Category("Data")]
    [DisplayName("All Floors Group")]
    [Description("All Floors Groupppppppppppppp")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public AllFloorsInformation AllFloorsInfo
    {
        get
        {
            return allFloorsInformation;
        }
        set
        {
            allFloorsInformation = value;
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
}

public class Tabs : CollectionBase
{
    public FloorsInformation this[int intIndex]
    {
        get
        {
            return (FloorsInformation)InnerList[intIndex];
        }
        set
        {
            InnerList[intIndex] = value;
        }
    }

    public int Add(FloorsInformation finfItemType)
    {
        return InnerList.Add(finfItemType);
    }

    public bool Contains(FloorsInformation finfItemType)
    {
        return InnerList.Contains(finfItemType);
    }

    public void Remove(FloorsInformation finfItemType)
    {
        InnerList.Remove(finfItemType);
    }

    public void Insert(int intIndex, FloorsInformation finfItemType)
    {
        InnerList.Insert(intIndex, finfItemType);
    }

    public FloorsInformation[] GetValues()
    {
        FloorsInformation[] finfItemType = new FloorsInformation[InnerList.Count];
        InnerList.CopyTo(0, finfItemType, 0, InnerList.Count);
        return finfItemType;
    }
}

顺便说一句,我可以在继承自“CollectionEditor”类的“ItemsCollectionEditor”类的“SetItems”覆盖方法中调用此方法;尽管如此,如果不创建自定义控件类的新实例,我将无法访问“AddTabs”方法。如果我创建自定义控件的新实例,“AddTabs”方法会将更改应用于自定义控件的新控件,而不是 WinForm 中当前添加的自定义控件。

public class ItemsCollectionEditor : CollectionEditor
{
    private Type[] typItems;

    public ItemsCollectionEditor(Type typItem)
        : base(typItem)
    {
        typItems = new Type[] { typeof(FloorsInformation) };
    }

    protected override Type[] CreateNewItemTypes()
    {
        return typItems;
    }

    protected override CollectionForm CreateCollectionForm()
    {
        CollectionForm collectionForm = base.CreateCollectionForm();
        collectionForm.Text = "Tabs Collection Editor";
        return collectionForm;
        //return base.CreateCollectionForm();
    }

    protected override object SetItems(object editValue, object[] value)
    {
        return base.SetItems(editValue, value);
    }
}

我必须做什么才能实现我的目标?

【问题讨论】:

    标签: c# winforms runtime custom-controls design-time


    【解决方案1】:

    你有几个选择。

    选项 1:

    如果您只想在设计时公开FloorsGrouping.Items 属性,您可以将Tab 属性的类型更改为SubItemsCollection 并返回Items 属性。在这种情况下,您不必担心拦截任何集合更改事件,它会自动为您发生。

    [Category("Data")]
    [DisplayName("Tabs")]
    [Description("Tabsssssssssssss")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Editor(typeof(ItemsCollectionEditor), typeof(UITypeEditor))]
    public SubItemsCollection Tab {
        get {
            return Items;
        }
    }
    

    选项 2:

    如果需要拦截集合变化事件,修改Tabs类继承自ObservableCollection&lt;FloorsInformation&gt;,实现INotifyCollectionChanged

    public class Tabs : System.Collections.ObjectModel.ObservableCollection<FloorsInformation> {
    }
    

    在您的 FloorsGrouping 构造函数中,订阅 CollectionChanged 事件。

    public FloorsGrouping() {
        ...
        tabs.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(tabs_CollectionChanged);
    }
    

    最后,在您的事件处理程序中,处理集合更改。

    private void tabs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
        switch (e.Action) {
            case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                foreach (DockContainerItem dciItem in e.NewItems) {
                    if (!Parent.Controls.ContainsKey(dciItem.Name))
                        Items.Add(dciItem);
                }
                break;
            case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                Items.Clear();
                break;
        }
    }
    

    您会注意到选项 2 是 CollectionChanged 事件在集合编辑器中实时触发,而不是在单击“确定”按钮时触发。但是,当用户最终在集合编辑器中单击“确定”或“取消”按钮时,集合的状态是准确的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 1970-01-01
      • 2014-04-22
      • 2012-05-21
      • 1970-01-01
      相关资源
      最近更新 更多