CheckedListBox check state not getting updated in tab conrtol


Hi,

I have a ChecekdListBox in a tab control. When I am setting the checked state of my CheckedListBox, it is not updating properly if the control i hidden in the tab page.

Run the attached sample.
Click Check button.
Now switch to tabPage2, notice that the checks are not placed.
Now click CheckButton again, notice that the checks are placed.

Is this a bug or am I doing something wrong?

thanks for your help,
- Reddy

-
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace CheckedListBoxTest
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.CheckedListBox checkedListBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.CheckedListBox checkedListBox2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

ArrayList list = new ArrayList();
list.Add(new StateDetails(1, "Alabama"));
list.Add(new StateDetails(2, "Arizona"));
list.Add(new StateDetails(3, "Arkansas"));
list.Add(new StateDetails(4, "Kansas"));
list.Add(new StateDetails(5, "New York"));
list.Add(new StateDetails(6, "New Mexico"));
list.Add(new StateDetails(7, "Texas"));

checkedListBox1.DataSource = list;
checkedListBox1.DisplayMember = "StateName";
checkedListBox1.ValueMember = "StateId";

checkedListBox2.DataSource = list;
checkedListBox2.DisplayMember = "StateName";
checkedListBox2.ValueMember = "StateId";
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (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.checkedListBox1 = new System.Windows.Forms.CheckedListBox();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.checkedListBox2 = new System.Windows.Forms.CheckedListBox();
this.label1 = new System.Windows.Forms.Label();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.SuspendLayout();
//
// checkedListBox1
//
this.checkedListBox1.Location = new System.Drawing.Point(16, 24);
this.checkedListBox1.Name = "checkedListBox1";
this.checkedListBox1.Size = new System.Drawing.Size(120, 94);
this.checkedListBox1.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(160, 40);
this.button1.Name = "button1";
this.button1.TabIndex = 2;
this.button1.Text = "Check";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(160, 80);
this.button2.Name = "button2";
this.button2.TabIndex = 3;
this.button2.Text = "Uncheck";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// tabControl1
//
this.tabControl1.Controls.AddRange(new System.Windows.Forms.Control[] {
this.tabPage1,
this.tabPage2});
this.tabControl1.Location = new System.Drawing.Point(24, 136);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(224, 160);
this.tabControl1.TabIndex = 4;
//
// tabPage1
//
this.tabPage1.Controls.AddRange(new System.Windows.Forms.Control[] {
this.label1});
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Size = new System.Drawing.Size(216, 134);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "tabPage1";
//
// tabPage2
//
this.tabPage2.Controls.AddRange(new System.Windows.Forms.Control[] {
this.checkedListBox2});
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Size = new System.Drawing.Size(216, 134);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "tabPage2";
//
// checkedListBox2
//
this.checkedListBox2.Location = new System.Drawing.Point(32, 16);
this.checkedListBox2.Name = "checkedListBox2";
this.checkedListBox2.Size = new System.Drawing.Size(120, 94);
this.checkedListBox2.TabIndex = 0;
//
// label1
//
this.label1.Location = new System.Drawing.Point(32, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(144, 72);
this.label1.TabIndex = 0;
this.label1.Text = "tabPage2 contains another CheckedListBox";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(280, 350);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.tabControl1,
this.button2,
this.button1,
this.checkedListBox1});
this.Name = "Form1";
this.Text = "Form1";
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage2.ResumeLayout(false);
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void button1_Click(object sender, System.EventArgs e)
{
for(int i =0; i < 7; i++)
{
checkedListBox1.SetItemChecked(i, true);
checkedListBox2.SetItemChecked(i, true);
}
}

private void button2_Click(object sender, System.EventArgs e)
{
for(int i =0; i < 7; i++)
{
checkedListBox1.SetItemChecked(i, false);
checkedListBox2.SetItemChecked(i, false);
}
}
}

public class StateDetails
{
private int stateId;
private string stateName;

public StateDetails(int stateId, string stateName)
{
this.stateId = stateId;
this.stateName = stateName;
}

public int StateId
{
get
{
return stateId;
}
set
{
stateId = value;
}
}

public string StateName
{
get
{
return stateName;
}
set
{
stateName = value;
}
}
}
}

-

[7588 byte] By [codefund.com] at [2007-12-16]
# 1
Good example. Certainly points out the problem. Looks like a bug to me--it may be "as designed" behavior, but it's not documented in the help file, if it is, and it sure seems odd. Looks like they're simply "throwing out" the call to SetItemChecked if the control isn't visible. If you interrogate the CheckedItems collection from the SelectedIndexChanged event of the Tab control (when moving from page 1 to page 2, where the list is displayed), they're really not checked.

One solution I see is writing code in SelectedIndexChanged event of the tab control, and if the checked list is going to be displayed, update its contents. Ugly, but it could work.

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 2
I got the following reply from on Syncfusion forms.

Yup, I've run into this as well. In Usenet posts, MS has acknowledged this bug. The problem is essentially that any time the visibility changes on a CheckedListBox, it loses its previous selections. Naturally this happens all the time in tab controls when changing tabs.

I think your best bet would be to listen to the events when the checked state of an item changes in the CheckedListBox and maintain a collection of checked items (separately from the CheckedListBox). If the CheckedListBox is hidden, it will lose its selections, but when it is shown again, you can restore the selection from your own collection. Something along those lines should work, I believe that's how we solved it in the past.

Can someone from Microsoft let us know when this will be fixed or if it is fixed already in .NET 1.1.

thanks,
- Reddy

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 3
If no one gets to this by monday, I'll check it in 1.1 when I get home. On the road this weekend with the beta installed.
codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 4
I derived my own control from a checked listbox and added the following code to fix this problem.

# region Workaround for CheckedListBox bug
//////////////////////////////////////////////////////////////////////
// When CheckedList box becomes invisible (e.g. when the tab page
// containing this control is overlapped with another tab page),
// checked state of the items are getting lost. This workaround will
// fix this problem
//////////////////////////////////////////////////////////////////////

private bool[] isItemChecked;
protected override void OnDataSourceChanged(EventArgs e)
{
base.OnDataSourceChanged(e);

int cnt = this.Items.Count;
isItemChecked = new Boolean[cnt];
for(int i = 0; i < cnt; i++)
{
isItemChecked[i] = GetItemChecked(i);
}
}

protected override void OnItemCheck(ItemCheckEventArgs e)
{
base.OnItemCheck(e);
isItemChecked[e.Index] = (e.NewValue == CheckState.Checked);
}

protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);

if (this.Visible == true)
{
for(int i =0; i < this.Items.Count; i++)
{
//Console.WriteLine("Checkstate["+i+"] = " + this.GetItemCheckState(i)
//+", new value="+isItemChecked[i]);
SetItemChecked(i, isItemChecked[i]);
}
}
}
#endregion

thanks for all your help,
- Reddy

codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 5
Good move. Glad you got it worked out.
codefund.com at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...