0

I am trying to make a warning window in an application. The window needs to run on a seperate thread and contains among other things a Canvas depicting a failing object. The Canvas already exists in the main application, and what i need is simply to show the same Canvas in the warning window. The problem is that i get an error saying that another thread owns the object. I tried doing a deep copy using this method but with no luck. Is there anything i missed, or is there really no simple method to copy a Canvas, or a collection of images. Alternatively, would it be possible to do the deep copy and then change the treading affinity of the copied object?

I should think that someone has encountered this problem before, but my serching skills have given me no relevant results this time.

Thanks in advance! -ruNury

EDIT 1

    private Canvas cloneCanvas()
    {
        Canvas testcanv = new Canvas();

        Dispatcher.Invoke(new Action(delegate
        {
            var t = SomeViewModel.GetCanvasWithImages();
            testcanv = CopyCanvas(t);
        }));

        return testcanv;
    }

    public static UIElement DeepCopy(UIElement element)
    {
        if (element != null)
        {
            var xaml = XamlWriter.Save(element);

            var xamlString = new StringReader(xaml);

            var xmlTextReader = new XmlTextReader(xamlString);

            var deepCopyObject = (UIElement)XamlReader.Load(xmlTextReader);

            return deepCopyObject;
        }

        return null;

    }

    private Canvas CopyCanvas(Canvas inputCanvas)
    {

        if (inputCanvas != null)
        {
            var outputCanvas = new Canvas();

            foreach (UIElement child in inputCanvas.Children)
            {
                outputCanvas.Children.Add(DeepCopy(child));
            }

            return outputCanvas;
        }

        return null;
    }
ruNury
  • 173
  • 2
  • 8
  • Only the thread that created a UI object (main) can access the UI object. – paparazzo May 09 '12 at 13:55
  • Yes, that is the reason why I need a COPY of the object which can be shown on the NEW thread... – ruNury May 09 '12 at 14:13
  • I feel your pain. I have tried to do this and gave up. It seems that even a copy of a UI object still a UI object. I know this seems extreme but you may needs to serialize to string and create the canvas. I even had to serialize a FlowDocument to string to pass it from background to the main. – paparazzo May 09 '12 at 14:38
  • The annoying part is that I can put a break point in the dispatcher and see that testcanv contains the right data, but as soon as the im outside the dispatcher, testcanv children are owned by another thread... – ruNury May 10 '12 at 08:08
  • Internally .NET only checks for ownership periodically. – paparazzo May 10 '12 at 12:01

1 Answers1

0

You can singleton pattern to maintain one object of warning window.

When you want to put the canvas into warning window, you have to use Dispatcher.

Dispatcher will marshal method call onto UI thread.

something like

  warningWindow.Dispatcher.Invoke(
      System.Windows.Threading.DispatcherPriority.Normal,
      new Action(
        delegate()
        {
          myCheckBox.IsChecked = true;
        }
    ));

Where warningWindow will be available through singleton instance

Tilak
  • 30,108
  • 19
  • 83
  • 131
  • I updated the question (should have included the code from the beginning). What I did is more or less what u suggest, but testcanv is not accessible at the return point. – ruNury May 09 '12 at 14:04
  • testcanv = CopyCanvas(t); --> it looks like the culprit. – Tilak May 09 '12 at 14:24
  • Instead of testCanvas= CopyCanvas(t), can you put testCanvas into a Grid in XAML (say grid1), and assign it like grid1.Children.Add(testCanvas); http://stackoverflow.com/questions/311131/add-wpf-control-at-runtime – Tilak May 09 '12 at 14:26
  • What will it help to put testcanv into a grid, when it is still not accessible in the warning window thread? As I see it the real problem is to have testcanv contain copies of the children in the 't' canvas... – ruNury May 10 '12 at 11:49