Pergunta

I have a WPF application that is utilizing the reporting tools included with Visual Studio 2010. I've had some other problems that I've solved by creating a graph of objects that are all marked as serializable, etc., as mentioned on various other web pages.

The ReportViewer control is contained in a WindowsFormsHost. I'm handling the SubreportProcessing event of the ReportViewer.LocalReport object to provide the data for the sub report.

The object graph that I'm reporting on is generated in my viewmodel, and that viewmodel holds a reference to it. The SubreportProcessing handler is in my code behind of my window (may not be the best place - but I simply want to get the ReportViewer working at this point).

Here's the problem: In my event handler, I'm attempting to get a reference to my viewmodel using the following code:

var vm = DataContext as FailedAssemblyReportViewModel;

When the handler is called, this line throws an InvalidOperationException with the message The calling thread cannot access this object because a different thread owns it.

I didn't realize the handler might be called on a different thread. How can I resolve this?

I attempted some searches, but all I've come up with is in regards to updating the UI from another thread using the Dispatcher, but that won't work in this case...

Foi útil?

Solução

I solved this problem using something I believe is a hack, by adding the following function:

public object GetDataContext() {
    return DataContext;
}

And then replacing the line of code from my question with:

object dc = Dispatcher.Invoke(new Func<object>(GetDataContext), null);
var vm = dc as FailedAssemblyReportViewModel;

However, this seems like a hack, and I might be circumventing some sort of safety check the CLR is doing. Please let me know if this is an incorrect way to accomplish this.

Outras dicas

That's a nasty problem you have there. Why don't you use in the view a content presenter which you bind to a windows form host? And in the view model you would have a property of type of type WindowsFormsHost. Also,in the view model's constructor you could set the windows form's host Child property with the report viewer. After that is smooth sailing, you could use your report viewer anywhere in your code. Something like this: View:

<ContentPresenter Content="{Binding Path=FormHost}"/>                        

ViewModel:

private ReportViewer report = new ReportViewer();
private WindowsFormsHost host = new WindowsFormsHost();
public WindowsFormsHost FormHost
{
 get {return this.host;}
 set
     {
      if(this.host!=value)
      {
      this.host = value;
      OnPropertyChanged("FormHost");
      }
     }
}


public ViewModel() //constructor
{
     this.host.Child = this.report;
}

After that happy coding. Hope it helps.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top