0

I am having a hard time creating a class where I can use ListBox to log events. I know i have tonnes of articles on what I am asking on SO and google but that i didn't make out of it. So i am asking a little help here:

I have three classes:

1: WinForm - Where my list box is placed. From here I pass my listbox in the FileEnumeratorClass() constructor.

2: FileEnumeratorClass - Recieving listbox here and then passing it to logger class.

class FileEnumeratorClass {
    UILogger logger;
    /// <summary>
    ///     ctor
    /// </summary>
    public FileEnumeratorClass (ListBox lbLog)
    {
        logger = new UILogger(lbLog);
    }

    /// <summary>
    ///     Figures out what has changed between the src and destination
    ///     What is currently implemented does not work......the solution is to compare SRC and DESTINATION for the first time.
    ///     And verify with end user.
    /// </summary>
    public List<FileDetails> IdentifyChanges()
    {
        logger.AddToLog("Change detection initiated...");
        //Deletes any existing cached package. Assuming it is in incosistent form
        logger.AddToLog( "Cleaning up any cached local package.");
        DeleteLocalPackage();
    } 
}

3: UILogger

public  class UILogger
{
    public UILogger(ListBox lb)
    {
        lbLog = lb;
    }
    // This delegate enables asynchronous calls for setting
    // the text property on a  control.
    delegate void AddToLogCallback(string text);

    public void AddToLog( string message)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (lbLog.InvokeRequired)
        {
            var d = new AddToLogCallback(AddToLog);
            lbLog.Invoke(d, new object[] { message });
        }
        else
        {
            // add this line at the top of the log
            lbLog.Items.Insert(0, message);

        }

        // keep only a few lines in the log
        while (lbLog.Items.Count > 1000)
        {
            lbLog.Items.RemoveAt(lbLog.Items.Count - 1);
        }
    }       
}

But the above code does not work as expected. All showing up when thread is done. What I need is to call the methods AddToLog() in the same sequence as they are written/called in FileEnumeratorClass -> IdentifyChanges().

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92

1 Answers1

-1

You need to call Control.Invalidate() method whenever you want the listbox to update its contents to force listbox to redraw itself. Please note that these control are thread safe which means any async or child thread must not update any UI control. Use proper callbacks to UI thread and let the UI thread update the control.

public List<FileDetails> IdentifyChanges()
{
    logger.AddToLog("Change detection initiated...");
    //Deletes any existing cached package. Assuming it is in incosistent form
    logger.AddToLog( "Cleaning up any cached local package.");

  //Invalidate the control to redraw.
    logger.Invalidate();

    DeleteLocalPackage();
} 
Artem Kulikov
  • 2,250
  • 19
  • 32
  • No, adding an element invalidates the control. The problem is that the control has no time to refresh itself until the operation is done. A forced `Refresh` would update the control; however, it should be avoided. – György Kőszeg Sep 07 '15 at 14:56