Why does the CheckedListBox lose checked state when placed in a tab page that gets hidden and shown?

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. This derived Control saves it’s state while getting hidden and reloads it while getting shown: [C#] # 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) { // Reset the checked states when it becomes visible. for(int i =0; i < this.Items.Count; i++) { SetItemChecked(i, isItemChecked[i]); } } } #endregion [VB.Net] Public Class MyCheckedListBox Inherits CheckedListBox ’//////////////////////////////////////////////////////////////////// ’ 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 isItemChecked() As Boolean Protected Overrides Sub OnDataSourceChanged(e As EventArgs) MyBase.OnDataSourceChanged(e) Dim cnt As Integer = Me.Items.Count isItemChecked = New [Boolean](cnt) {} Dim i As Integer For i = 0 To cnt – 1 isItemChecked(i) = GetItemChecked(i) Next i End Sub ’OnDataSourceChanged Protected Overrides Sub OnItemCheck(e As ItemCheckEventArgs) MyBase.OnItemCheck(e) isItemChecked(e.Index) = e.NewValue = CheckState.Checked End Sub ’OnItemCheck Protected Overrides Sub OnVisibleChanged(e As EventArgs) MyBase.OnVisibleChanged(e) If Me.Visible = True Then ’ Reset the checked states when it becomes visible. Dim i As Integer For i = 0 To (Me.Items.Count) – 1 SetItemChecked(i, isItemChecked(i)) Next i End If End Sub ’OnVisibleChanged End Class ’MyCheckedListBox (Contributed by Eric and Reddy Duggempudi in Syncfusion Windows Forms FAQ forums).

How do I get hold of the currently focused Control?

The .Net framework libraries does not provide you an API to query for the focused Control. You have to invoke a windows API to do so: [C#] public class MyForm : Form { [DllImport(‘user32.dll’, CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)] internal static extern IntPtr GetFocus(); private Control GetFocusedControl() { Control focusedControl = null; // To get hold of the focused control: IntPtr focusedHandle = GetFocus(); if(focusedHandle != IntPtr.Zero) // Note that if the focused Control is not a .Net control, then this will return null. focusedControl = Control.FromHandle(focusedHandle); return focusedControl; } } [VB.Net] Public Class Form1 ’ Declare the GetFocused method here: _ Public Shared Function GetFocus() As IntPtr End Function Private Function GetFocusedControl() As Control Dim focusedControl As Control = Nothing ’ To get hold of the focused control: Dim focusedHandle As IntPtr = GetFocus() If IntPtr.Zero.Equals(focusedHandle) Then ’ Note that if the focused Control is not a .Net control, then this will return null. focusedControl = Control.FromHandle(focusedHandle) End If Return focusedControl End Function End Class

How do I control the order in which events are fired to multiple subscribers?

In C#, you can do as follows: // Use a custom Delegate to hold your subscribers private EventHandler myHandlers; // Control Click event firing, for example. public new event EventHandler Click { add { this.myHandlers += value; } remove { this.myHandlers -= value; } } protected override void OnClick(EventArgs e) { // First let my derived classes receive the Click event. foreach(Delegate d in this.myHandler.GetInvocationList()) { if(d.Target == this) { d.DynamicInvoke(new object[]{this, e}); break; } } // Then let other subscribers receive the Click event. foreach(Delegate d in this.myHandler.GetInvocationList()) { if(d.Target != this) d.DynamicInvoke(new object[]{this, e}); } }