Customer question roundup

I've been heads down working on a project lately, and I've let a few questions build up.  My apologies for this, here's what I have (if it's still useful):

Updates from Everen on fixing the disabled drawing for the ever-popular SplitButton sample.
I've just wanted to thank you for the SplitButton code. Only glitch was that it wasn't rendering correctly when it was Disabled so i've added a check at the start of the OnPaint function to set the _state to PushButtonState.Disabled. Also added checks at the arrow and text rendering lines to render in Control.GrayText color.

Question on Control.Invoke
I'm surfing a treeview in a worker thread and I want to know if it's better to use Control.Invoke for this situation?
If you're not changing state, you might "get away" with this, but Invoke would ensure robustness as the treeview wont change out from underneath you.  The rule of thumb is touch the UI stuff only on the UI thread.  If you can use 2.0 try to keep CheckForIllegalCrossThreadCalls turned on.

Also, do you know if the "TreeNode.Tag" member (or any ".Tag" member of any control for that matter) needs to be invoked on the creating thread as well? Since this property really just stores raw programmer data I'm not sure if it's really necessary.

The "Tag" property is just an object.  But how you get a hold of the TreeNode on the secondary thread may be problematic (see the first response).  I would recommend keeping your data separate from your UI - use a hashtable or dictionary that both threads can look at - and take either locks as appropriate (if they're both using the same list) or use a BackgroundWorker style ReportProgress event:  the background thread presents a list which the UI thread copies and applies.

Question on ToolStripSettings
I was just wondering if there is anyway to save the Toolstrip to a non-default settings provider?
Unfortunately, this was an omission in the design.  You'd have to redo the settings persistence yourself.

Question on UnhandledExceptions
What exactly is an unhandled exception? Is this not a Unhadled Exception? if this is then why my ThreadException handler is not getting invoked?

try
{
throw Exception();
}
//No catch block
finally
{

}

An Unhandled exception is when there is no catch block in the callstack.  If you're using the System.Windows.Forms.Application.ThreadException event to trap unhandled exceptions, you should know that the "catch" block under the covers only works when the message pump has already been started.  So if you throw from main before Application.Run or in the constructor while creating the argument you're passing into Application.Run or throw from a background thread, the ThreadException dialog might not be there for you.  Here's an example:

using System;
using System.Windows.Forms;

namespace Test {

   public class Form1 : Form {

       public Form1() {
         // This object isn't run under the message loop yet!  Application.Run hasn't been called! 
         try  {
            throw new Exception();
          }
          //No catch block
          finally {
          }
       }

       [STAThread]
       public static void Main() {
          // how it's typically written
          Application.Run(new Form1());

         // another way of writing the same code is:

         // Form1 f = new Form1();
         // Application.Run(f);

  
       }
   }
}

If you hook onto a few more things, you can get a more systematic approach to catching errors outside the message loop.

Happy Holidays!
JFo