Question

I use 4 WPF User Controls in a single Application. Each of the User Controls launch their own threads to do stuff at the end of which I want them to only update the ListBox present in their respective User Control.

I tried using a static variable in the User Control code to hold either the instance of the User Control or even its ListBox, but that results in only the last User Control ListBox being written to (by the wrong thread).

I've even tried stuff like this

private static ListBox1 = null;
private static ListBox2 = null;
private static ListBox3 = null;
private static ListBox4 = null;
private static ListBoxToUse;

then on initialization of each UserControl

if (ListBox1 == null)
{
    ListBox1 = this;
    ListToUse = this;
}
else if (ListBox2 == null)
{
    ListBox2 = this;
    ListToUse = this;
} ...

and then

ListBoxToUse.Dispatcher.BeginInvoke(new Action(delegate()
{
    ListBoxToUse.Items.Add("......");
}));

But that didn't work either. Any suggestions please?

Edit 1 :-

Following is my thread code

    private class CopyPortDevFileThread
    {
        public MyWorkingDirectoryInfo WorkingDirectory { get; set; }
        public PortableDeviceFile PortDevFileToCopy { get; set; }
        public string DestinationDir { get; set; }

        public void CopyFile()
        {
            Debug.WriteLine("CopyFile DestinationDir " + DestinationDir);
            // To fix Samsung NT-7000 bug of giving the Id when Path.GetFilename() is called
            string gfn = Path.GetFileName(PortDevFileToCopy.Id);
            string fn = DestinationDir + "\\" + gfn;
            WorkingDirectory.USBDevice.DownloadFile(PortDevFileToCopy, DestinationDir);
            if (!IsValidFilename(gfn))
            {
                // Rename file if name is okay
                if (IsValidFilename(PortDevFileToCopy.Name))
                {
                    int sec = 5;
                    while (sec > 0)
                    {
                        if (IsFileReady(fn))
                        {
                            File.Move(fn, Path.Combine(DestinationDir, PortDevFileToCopy.Name));
                            fn = Path.Combine(DestinationDir, PortDevFileToCopy.Name);
                            sec = 0;
                        }
                        else
                        {
                            Console.WriteLine("Waiting .....");
                            System.Threading.Thread.Sleep(1000);
                        }
                        sec -= 1;
                    }
                }
            }
        }
    }

Then the call to the thread from the code of the User Control

    private void CopyPortDevDocument(PortableDeviceFile _file, string _destDir)
    {
        Debug.WriteLine("CopyPortDevDocument with destination directory " + _destDir);
        if (_file == null)
        {
            return;
        }
        if (_destDir == null)
        {
            return;
        }
        if ((System.IO.Directory.Exists(_destDir)))
        {
            CopyPortDevFileThread cpdft = new CopyPortDevFileThread();
            cpdft.WorkingDirectory = Pwd;
            cpdft.PortDevFileToCopy = _file;
            cpdft.DestinationDir = _destDir;
            Thread cpdfThread = new Thread(new ThreadStart(cpdft.CopyFile));
            cpdfThread.Start();

            LogOutput(@"creating " + _destDir + "\\" + _file.Name);
        }
    }
Was it helpful?

Solution

You don't need these static fields. Just assign the x:Name property of the ListBox control in the UserControl XAML. Then you can access the ListBox as member of the UserControl class:

<UserControl x:Class="UserControlTest.MyUserControl" ...>
    <Grid>
        <ListBox x:Name="list" .../>
        ...
    </Grid>
</UserControl>

The above XAML creates a field list of type ListBox in class MyUserControl.


Update: Change the CopyFile method of your thread class so that it accepts a parameter of type object and then cast that object to a UserControl reference:

public void CopyFile(object parameter)
{
    var userControl = parameter as MyUserControl;
    ...
}

Then start your thread with the UserControl reference parameter like this:

var cpdfThread = new Thread(new ParameterizedThreadStart(cpdft.CopyFile));
cpdfThread.Start(this); // where this is the UserControl reference

Another alternative would be to just add the UserControl reference as property to your CopyPortDevFileThread class.

Instead of creating a new Thread for excuting the CopyFile method you may also use a ThreadPool thread by e.g. calling ThreadPool.QueueUserWorkItem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top