Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add sub controls to custom control after click the "OK" button of the "CollectionEditor" window in design time

I've created my custom control. It has a property that is called "Tab." This property adds a collection of "FloorsInformation" controls that are inherited from "DockContainerItem" class to my custom control.

My custom control properties

Now, I want to add "FloorsInformation" controls to my custom control after click the "OK" button of the Tab "CollectionEditor" window.

"Tabs Collection Editor" window

I have "AddTabs" method for doing that. However, I can't call it in the right place. I must call "AddTabs" method in "set accessor" of the "Tab" property, but it never occurs.

I also can call this method from "get accessor" of the "Tab" property, but calling this method in "get accessor" of the "Tab" property will result in an error, because the program access to the "get accessor" of the "Tab" property continuously.

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

By the way, I can call this method in "SetItems" overrode method of the "ItemsCollectionEditor" class that is inherited from "CollectionEditor" class; nevertheless, I can't access to "AddTabs" method without create a new instance of my custom control class. If I create a new instance of my custom control, "AddTabs" method applies changes on a new control of my custom control and not on the current added custom control in the 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);
    }
}

What must I do for achieve to my goal?

like image 215
MRS1367 Avatar asked Nov 21 '12 13:11

MRS1367


1 Answers

You have a couple of options.

Option 1:

If you are just wanting to expose the FloorsGrouping.Items property at design time, you can change the Tab property's type to SubItemsCollection and return the Items property. In this case, you won't have to worry about intercepting any collection change events, it will happen for you automatically.

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

Option 2:

If you are needing to intercept the collection change events, modify the Tabs class to inherit from ObservableCollection<FloorsInformation>, which implements INotifyCollectionChanged.

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

And in your FloorsGrouping constructor, subscribe to the CollectionChanged event.

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

Finally, in your event handler, process the collection change.

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

What you'll notice with option 2 is that the CollectionChanged event fires in real time with the editing in the collection editor, not specifically when the OK button is clicked. However, when the user finally clicks the OK or Cancel button in the collection editor, the collection's state is accurate.

like image 127
cokeman19 Avatar answered Nov 19 '22 14:11

cokeman19