Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind Data to Windows Form TabControl

I'm attempting my first Windows Form project, having been entirely web based previously and experiencing some issues. I want to bind a list of objects to a TabControl and have this create the Tabs and then have a databound value accessible from the click event of each tab.

The Object I'm wanting to bind is

public class TreeNodeItem
{
    private NTree<string> node;

    public TreeNodeItem(NTree<string> node)
    {
        this.node = node;
    }

    public string Value
    {
        get { return this.node.data; }
    }
}

The NTree node represents a node in an object that models data in a tree structure. I want to create a tab for each object in the list with the Value property being bound to the Tab Text property. Other posts mention binding to the ItemsSource property of the control, but Visual Studio is not giving me this property.

Any help will be greatly appreciated.

Cheers

Stewart

like image 908
Stewart Alan Avatar asked Aug 30 '12 10:08

Stewart Alan


People also ask

How do you use TabControl?

To create a TabControl control at design-time, you simply drag and drop a TabControl control from Toolbox onto a Form in Visual Studio. After you drag and drop a TabControl on a Form, the TabControl1 is added to the Form and looks like Figure 1. A TabControl is just a container and has no value without tab pages.

Which of the following is the correct way to add a new page to the tab control programmatically?

To add a tab programmaticallyUse the Add method of the TabPages property.


1 Answers

Okay, I was unaware of that the binding was a must. Although I have never seen something like this being done in a Windows Forms Application, I've decided to create a class that does this for us.

It uses the ObservableCollection<T> to keep track whether an object / property has been changed inside its list.

    public class ObservableList<T> : ObservableCollection<T>
    {
        public ObservableList() : base()
        {
            CollectionChanged += new NotifyCollectionChangedEventHandler(nObservableCollection_CollectionChanged);
        }

        public event PropertyChangedEventHandler OnPropertyChanged;

        void nObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (OnPropertyChanged != null)
            {
                OnPropertyChanged(new object[] { e.OldItems, e.NewItems }, null); // Call method to let it change the tabpages
            }
        }
    }

Now, we have to create a helper class that helps us keeping track:

    public class TabControlBind
    {
        public TabControlBind(TabControl tabControl)
        {
            // Create a new TabPageCollection and bind it to our tabcontrol
            this._tabPages = new TabControl.TabPageCollection(tabControl);
        }

        // Fields
        private ObservableList<TreeNodeItem> _treeNodeItems;
        private TabControl.TabPageCollection _tabPages;

        // Properties
        public ObservableList<TreeNodeItem> TreeNodeItems
        {
            get { return _treeNodeItems; }
            set
            {
                if (_treeNodeItems != value)
                {
                    _treeNodeItems = value;
                    _treeNodeItems.OnPropertyChanged += OnPropretyChanged;
                    OnPropretyChanged(null, null);
                }
            }
        }

        public TabControl.TabPageCollection TabPages
        {
            get
            {
                return this._tabPages;
            }
        }

        // Events
        private void OnPropretyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (sender == null) // If list got set
            {
                // Remove existing tabpages
                this._tabPages.Clear();

                // Loop through all items inside the ObservableList object and add them to the Tabpage
                foreach (TreeNodeItem _treeNodeItem in this._treeNodeItems)
                {
                    TabPage tabPage = new TabPage() { Text = _treeNodeItem.Value, Tag = _treeNodeItems };
                    this._tabPages.Add(tabPage);
                }
            }
            else if (sender is object[]) // If only one (or multiple) objects have been changed
            {
                // Get OldItems and NewItems
                object[] changedItems = (object[])sender;
                // Remove OldItems
                if (changedItems[0] != null)
                {
                    foreach (dynamic oldItems in (IList)changedItems[0])
                    {
                        foreach (TabPage tab in this._tabPages)
                        {
                            if (tab.Text == oldItems.Value)
                            {
                                this._tabPages.Remove(tab);
                                break;
                            }
                        }

                    }
                }
                // Add OldItems
                if (changedItems[1] != null)
                {
                    foreach (dynamic newItems in (IList)changedItems[1])
                    {
                        TabPage tabPage = new TabPage() { Text = newItems.Value, Tag = newItems };
                        this._tabPages.Add(tabPage);
                    }
                }
            }
        }
    }

This is a sample on how to use it:

    TabControlBind tabControlBinder;
    ObservableList<TreeNodeItem> treeNodeItems;

    private void btnAdd_Click(object sender, EventArgs e)
    {
        // This will automatically update the TabControl
        treeNodeItems.Add(new TreeNodeItem(new NTree<string>() { data = "Test3" }));
    }

    private void frmMain_Load(object sender, EventArgs e)
    {
        // Create a new list object an add items to it
        treeNodeItems = new ObservableList<TreeNodeItem>();
        treeNodeItems.Add(new TreeNodeItem(new NTree<string>() { data = "Test" }));
        treeNodeItems.Add(new TreeNodeItem(new NTree<string>() { data = "Test2" }));

        // Create a new instance of the TabControlBind class, set it to our TabControl
        tabControlBinder = new TabControlBind(tabControl);
        tabControlBinder.TreeNodeItems = treeNodeItems;
    }
like image 159
Jevgeni Geurtsen Avatar answered Oct 07 '22 11:10

Jevgeni Geurtsen