none
Comboboxes with same DataSource on multiple Tabpages RRS feed

  • Question

  • Hi there, I have a very strange problem. I'm using a TabControl with 3 TabPages on an UserControl.

    On the 2nd and 3rd tab I've added a GrouBox, within those GroupBoxes are ComboBoxes.

    In the constructor I've created and assigned the same BindingList<Type> to both ComboBoxes. When I fill the DataSource (BindingList) the first ComboBox, on Page 2, is filled with the added values of the shared DataSource. The second on the 3rd page ComboBox doesn't fill, it's empty. When I move the ComboBox from the 3rd page to the 2nd page it worked like a charm.

    This is a snippet of my constructor:

    _ds = new BindingList<MyType>();
    CmbTabPage2.BindingContext = new BindingContext();
    CmbTabPage2.DisplayMember = "Name";
    CmbTabPage2.DataSource = _ds;
    CmbTabPage3.BindingContext = new BindingContext();
    CmbTabPage3.DisplayMember = "Name";
    CmbTabPage3.DataSource = _ds;

    The weird thing is... even if I don't assign the DataSource e on TabPage2, the ComboBox on TabPage 3 won't fill with the values of the DataSource neither. I really need help here.. It drives me to dispair... Please help. ._.



    • Edited by [Raiken] Wednesday, September 5, 2018 12:16 PM
    Wednesday, September 5, 2018 9:30 AM

Answers

  • Hi [Raiken],

    I have downloaded the project and reproduce the issue on my side, please modify your code like this:

    private SomeList<MyType> _ds;
    
            public Form1()
            {
    
                InitializeComponent();
                //var client = new Client();
                //_ds = new SomeList<MyType>() { Client = client };
                //CmbTabPage2.BindingContext = new BindingContext();
                //CmbTabPage2.DisplayMember = "Name";
                //CmbTabPage2.DataSource = _ds;
                //CmbTabPage3.BindingContext = new BindingContext();
                //CmbTabPage3.DisplayMember = "Name";
                //CmbTabPage3.DataSource = _ds;
                //tabControl1.SelectedTab = tabPage3;
            }
    
    
            private void button1_Click(object sender, EventArgs e)
            {
                
                try
                {
                    Cursor.Current = Cursors.WaitCursor;
                    _ds.FillList();
                    _ds.Wait();
                    CmbTabPage2.DataSource = _ds;
                    CmbTabPage2.DisplayMember = "Name";
                    CmbTabPage3.DataSource = _ds;
                    CmbTabPage3.DisplayMember = "Name";
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    //Let's pretend this is where I received the TCP Stuff.
                    Cursor.Current = Cursors.Default;
                    _ds.Reset();
    
                   
                    //CmbTabPage2.Invalidate();
                    //CmbTabPage3.Invalidate();
                }
            }

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by [Raiken] Thursday, September 13, 2018 10:25 AM
    Thursday, September 13, 2018 9:18 AM
    Moderator

All replies

  • Hi Raiken Inkognito,

    Based on your description and related code, I create a simple sample, but it works fine, could you please share a simple demo via OneDrive, which could reproduce the issue. 

    #My Sample.

    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form24 : Form
        {
            public Form24()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
              List<MyType> _ds = new List<MyType>() { new MyType(){ Name = "TestName", Value = "TestValue" },
                    new MyType() { Name = "TestName2", Value = "TestValue2" },
                    new MyType() { Name = "TestName3", Value = "TestValue3" },
                    new MyType() { Name = "TestName4", Value = "TestValue4" },
                };
    
                CmbTabPage1.BindingContext = new BindingContext();
                CmbTabPage1.DisplayMember = "Name";
                CmbTabPage1.DataSource = _ds;
    
                CmbTabPage2.BindingContext = new BindingContext();
                CmbTabPage2.DisplayMember = "Name";
                CmbTabPage2.DataSource = _ds;
                CmbTabPage3.BindingContext = new BindingContext();
                CmbTabPage3.DisplayMember = "Name";
                CmbTabPage3.DataSource = _ds;
            }
        }
    
        public class MyType
        {
            public string Name { get; set; }
            public string Value { get; set; }
        }
    }
    

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, September 6, 2018 1:56 AM
    Moderator
  • Thank you for your help, I've reproduced the error, somehow the 3rd one now get's filled and the second doesn't.

    Here's the sampe code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace TestTest
    {
        public partial class Form1 : Form
        {
            private SomeList<MyType> _ds;
    
            public Form1()
            {
                var client = new Client();
                InitializeComponent();
                _ds = new SomeList<MyType>() { Client = client };
                
                CmbTabPage2.BindingContext = new BindingContext();
                CmbTabPage2.DisplayMember = "Name";
                CmbTabPage2.DataSource = _ds;
                CmbTabPage3.BindingContext = new BindingContext();
                CmbTabPage3.DisplayMember = "Name";
                CmbTabPage3.DataSource = _ds;
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                
                try
                {
                    Cursor.Current = Cursors.WaitCursor;
                    _ds.FillList();
                    _ds.Wait();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    //Let's pretend this is where I received the TCP Stuff.
                    Cursor.Current = Cursors.Default;
                    _ds.Reset();
                }
            }
    
    
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Windows Form Designer generated code
    
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.tabControl1 = new System.Windows.Forms.TabControl();
                this.tabPage1 = new System.Windows.Forms.TabPage();
                this.button1 = new System.Windows.Forms.Button();
                this.tabPage2 = new System.Windows.Forms.TabPage();
                this.CmbTabPage2 = new System.Windows.Forms.ComboBox();
                this.tabPage3 = new System.Windows.Forms.TabPage();
                this.groupBox1 = new System.Windows.Forms.GroupBox();
                this.groupBox2 = new System.Windows.Forms.GroupBox();
                this.CmbTabPage3 = new System.Windows.Forms.ComboBox();
                this.tabControl1.SuspendLayout();
                this.tabPage1.SuspendLayout();
                this.tabPage2.SuspendLayout();
                this.tabPage3.SuspendLayout();
                this.groupBox1.SuspendLayout();
                this.groupBox2.SuspendLayout();
                this.SuspendLayout();
                // 
                // tabControl1
                // 
                this.tabControl1.Controls.Add(this.tabPage1);
                this.tabControl1.Controls.Add(this.tabPage2);
                this.tabControl1.Controls.Add(this.tabPage3);
                this.tabControl1.Location = new System.Drawing.Point(0, 0);
                this.tabControl1.Name = "tabControl1";
                this.tabControl1.SelectedIndex = 0;
                this.tabControl1.Size = new System.Drawing.Size(695, 374);
                this.tabControl1.TabIndex = 0;
                // 
                // tabPage1
                // 
                this.tabPage1.Controls.Add(this.button1);
                this.tabPage1.Location = new System.Drawing.Point(4, 22);
                this.tabPage1.Name = "tabPage1";
                this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
                this.tabPage1.Size = new System.Drawing.Size(687, 348);
                this.tabPage1.TabIndex = 0;
                this.tabPage1.Text = "tabPage1";
                this.tabPage1.UseVisualStyleBackColor = true;
                // 
                // button1
                // 
                this.button1.Location = new System.Drawing.Point(8, 6);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(75, 23);
                this.button1.TabIndex = 0;
                this.button1.Text = "button1";
                this.button1.UseVisualStyleBackColor = true;
                this.button1.Click += new System.EventHandler(this.button1_Click);
                // 
                // tabPage2
                // 
                this.tabPage2.Controls.Add(this.groupBox1);
                this.tabPage2.Location = new System.Drawing.Point(4, 22);
                this.tabPage2.Name = "tabPage2";
                this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
                this.tabPage2.Size = new System.Drawing.Size(687, 348);
                this.tabPage2.TabIndex = 1;
                this.tabPage2.Text = "tabPage2";
                this.tabPage2.UseVisualStyleBackColor = true;
                // 
                // CmbTabPage2
                // 
                this.CmbTabPage2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
                this.CmbTabPage2.FormattingEnabled = true;
                this.CmbTabPage2.Location = new System.Drawing.Point(31, 44);
                this.CmbTabPage2.Name = "CmbTabPage2";
                this.CmbTabPage2.Size = new System.Drawing.Size(121, 21);
                this.CmbTabPage2.TabIndex = 0;
                // 
                // tabPage3
                // 
                this.tabPage3.Controls.Add(this.groupBox2);
                this.tabPage3.Location = new System.Drawing.Point(4, 22);
                this.tabPage3.Name = "tabPage3";
                this.tabPage3.Size = new System.Drawing.Size(687, 348);
                this.tabPage3.TabIndex = 2;
                this.tabPage3.Text = "tabPage3";
                this.tabPage3.UseVisualStyleBackColor = true;
                // 
                // groupBox1
                // 
                this.groupBox1.Controls.Add(this.CmbTabPage2);
                this.groupBox1.Location = new System.Drawing.Point(6, 6);
                this.groupBox1.Name = "groupBox1";
                this.groupBox1.Size = new System.Drawing.Size(200, 100);
                this.groupBox1.TabIndex = 1;
                this.groupBox1.TabStop = false;
                this.groupBox1.Text = "groupBox1";
                // 
                // groupBox2
                // 
                this.groupBox2.Controls.Add(this.CmbTabPage3);
                this.groupBox2.Location = new System.Drawing.Point(6, 6);
                this.groupBox2.Name = "groupBox2";
                this.groupBox2.Size = new System.Drawing.Size(200, 100);
                this.groupBox2.TabIndex = 2;
                this.groupBox2.TabStop = false;
                this.groupBox2.Text = "groupBox2";
                // 
                // CmbTabPage3
                // 
                this.CmbTabPage3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
                this.CmbTabPage3.FormattingEnabled = true;
                this.CmbTabPage3.Location = new System.Drawing.Point(31, 44);
                this.CmbTabPage3.Name = "CmbTabPage3";
                this.CmbTabPage3.Size = new System.Drawing.Size(121, 21);
                this.CmbTabPage3.TabIndex = 0;
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(800, 450);
                this.Controls.Add(this.tabControl1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.tabControl1.ResumeLayout(false);
                this.tabPage1.ResumeLayout(false);
                this.tabPage2.ResumeLayout(false);
                this.tabPage3.ResumeLayout(false);
                this.groupBox1.ResumeLayout(false);
                this.groupBox2.ResumeLayout(false);
                this.ResumeLayout(false);
    
            }
    
            #endregion
    
            private System.Windows.Forms.TabControl tabControl1;
            private System.Windows.Forms.TabPage tabPage1;
            private System.Windows.Forms.TabPage tabPage2;
            private System.Windows.Forms.ComboBox CmbTabPage2;
            private System.Windows.Forms.TabPage tabPage3;
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.GroupBox groupBox1;
            private System.Windows.Forms.GroupBox groupBox2;
            private System.Windows.Forms.ComboBox CmbTabPage3;
        }
    
        public delegate void MessageHandler(object sender, MessageArgs args);
    
        public class MessageArgs : EventArgs
        {
            public object Packet { get; }
            public MessageArgs(object packet) => this.Packet = packet;
        }
    
        public interface IHasId
        {
            int Id { get; set; }
        }
    
        public interface IHasIdName : IHasId
        {
            string Name { get; set; }
        }
    
        public class MyType : IHasIdName
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    
        public class Client
        {
            public MessageHandler OnMessageReceive { get; set; }
        }
    
        public class SomeList<T> : BindingList<T> where T : IHasId
        {
            private event MessageHandler _handler;
            private ManualResetEvent _resetEvent = new ManualResetEvent(true);
    
            private Client _client;
            public Client Client {
                get => _client;
                set {
                    _client = value;
                    _client.OnMessageReceive += HandleMessage;
                }
            }
    
            public void FillList()
            {
                _handler += Received;
                _resetEvent.Reset();
                // Some TCP Stuff
            }
    
            public void Wait()
            {
                var at = new Thread(() =>
                {
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                    var list = new List<MyType>();
                    list.Add(new MyType() { Id = 0, Name = "First" });
                    list.Add(new MyType() { Id = 1, Name = "Second" });
                    // Let's pretend we receiving the correct TCP stuff.
                    HandleMessage(this, new MessageArgs(list));
                });
                at.SetApartmentState(ApartmentState.STA);
                at.Start();
                if (!_resetEvent.WaitOne(TimeSpan.FromSeconds(30)))
                    throw new Exception("Failed to receive List!");
            }
    
            public void Reset()
            {
                _resetEvent.Set();
                _handler -= Received;
            }
    
            private void HandleMessage(object sender, MessageArgs args)
            {
                _handler?.Invoke(sender, args);
            }
    
            private void Received(object sender, MessageArgs args)
            {
                lock (this)
                {
                    var list = (List<T>)args.Packet;
                    this.Clear();
                    foreach (var item in list)
                        this.Add(item);
                }
                _resetEvent.Set();
                _handler -= Received;
            }
        }
    
        public class Program
        {
            public static void Main(string[] args)
            {
                // Maybe disabling those two lines, run, and enable them again may reproduce the weird behavior
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
    
    
                Application.Run(new Form1());
            }
        }
    }


    Reproduced the error... when I first show the tabs, then press on the button, the comboboxes stay empty:

    Showing all tabs first before Button Click h t t p s://gyazo.com/2fd811e6793104bd324c5f5fa0f598f2

    Showing only tab 2 before Button Click h t t p s://gyazo.com/ecf792f91ce13024ba47195c07c34bce

    Also if I don't open Tab 2 or 3, and then click on the button, the comboboxes on both are filled like it should. But in my Application I show the 3rd tab first...

    I've added the code to the constructor:

    tabControl1.SelectedTab = tabPage3;

    And moved the button to tabPage3.

    This is what happens:

    Starting with Tab 3 h t t p s://gyazo.com/2e1cf83217aa3360f46b34bc5ea05f14

    Sorry for those links, it says I can't post links or images because my account needs to be vertified.

    • Edited by [Raiken] Thursday, September 6, 2018 7:44 AM
    Thursday, September 6, 2018 7:28 AM
  • Hi [Raiken],

    Could you please share the completed project via OneDrive?

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, September 11, 2018 8:06 AM
    Moderator
  • Thanks for your help @Zhanglong Wu,

    Here's the link https://1drv.ms/f/s!Ak4J-4ORJX2mgxiiopWmX-7NpPgw

    Thursday, September 13, 2018 7:23 AM
  • Hi [Raiken],

    I have downloaded the project and reproduce the issue on my side, please modify your code like this:

    private SomeList<MyType> _ds;
    
            public Form1()
            {
    
                InitializeComponent();
                //var client = new Client();
                //_ds = new SomeList<MyType>() { Client = client };
                //CmbTabPage2.BindingContext = new BindingContext();
                //CmbTabPage2.DisplayMember = "Name";
                //CmbTabPage2.DataSource = _ds;
                //CmbTabPage3.BindingContext = new BindingContext();
                //CmbTabPage3.DisplayMember = "Name";
                //CmbTabPage3.DataSource = _ds;
                //tabControl1.SelectedTab = tabPage3;
            }
    
    
            private void button1_Click(object sender, EventArgs e)
            {
                
                try
                {
                    Cursor.Current = Cursors.WaitCursor;
                    _ds.FillList();
                    _ds.Wait();
                    CmbTabPage2.DataSource = _ds;
                    CmbTabPage2.DisplayMember = "Name";
                    CmbTabPage3.DataSource = _ds;
                    CmbTabPage3.DisplayMember = "Name";
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    //Let's pretend this is where I received the TCP Stuff.
                    Cursor.Current = Cursors.Default;
                    _ds.Reset();
    
                   
                    //CmbTabPage2.Invalidate();
                    //CmbTabPage3.Invalidate();
                }
            }

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by [Raiken] Thursday, September 13, 2018 10:25 AM
    Thursday, September 13, 2018 9:18 AM
    Moderator
  • Thanks for your help. It works now, when I don't uncomment this Line:

    //_ds = new SomeList<MyType>() { Client = client };
    But how come it doesn't work the way I did it?

    • Edited by [Raiken] Thursday, September 13, 2018 10:28 AM
    Thursday, September 13, 2018 10:25 AM
  • Hi Raiken,

    It's never a good idea to put that kind of thing (databinding, etc.) in the Form's Constructor. Typically the code in the Constructor is simply for setting up all the controls, design-wise, on your Form. Try not to put a lot of other excess code in the Constructor.  

    In Zhanglong's example, he put it in a button Click event handler, but the best place to put it is going to be in your Form's Load event handler.


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Friday, September 14, 2018 1:12 AM
  • Thanks for the answer @BonnieB!
    Friday, September 14, 2018 10:30 AM
  • You're welcome, @Raiken!  =0)

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Friday, September 14, 2018 1:52 PM