views:

49

answers:

2

I am building an application in the MVVM style where the actual views (UserControls) are stored remotely and hopefully sent via a WCF service to my main application window. I am doing this in order to avoid having the user reinstall the application each time a new view is added. However, when I try to return a User Control from my WCF service I get an error stating:

System.Runtime.Serialization.InvalidDataContractException: Type 'System.Windows.Input.TouchDevice' cannot be serialized.

I am wondering if there is any way around this or if people have implemented something similar in other ways?

Thanks, Ochowie

A: 

What you're trying to do doesn't really make sense... controls are not DTOs, they're strongly dependent on their runtime environment. In WPF, there is also the issue of the dispatcher : even if you could transfer a control, how would you reattach it to your application dispatcher ? Anyway WPF controls are not serializable with the DataContractSerializer, and there is no way to change that.

However, what you could do is transfer a representation of the views in XAML. This is of course assuming your views are XAML only, without any code-behind. You could then load the views using XamlReader and render them in your UI. I'm not sure of the feasibility, but I think it's your best option.

You could also implement your views in a separate assembly, so that the users don't need to reinstall the whole application. They will only need to upgrade the modified assemblies.

Thomas Levesque
I guess that sending the raw XAML would work. I'm not sure what you mean about the dispatcher though. How is what I am trying to do any different from dynamically loading a user control based on something a user has selected which is certainly doable if the view's assembly is referenced?
Ochowie
When you instantiate a control, it is automatically attached to the current thread dispatcher. If you then send it to another machine, what is supposed to happen ? You won't be able to use it. But anyway you can't serialize it, so the point is moot...
Thomas Levesque
+1  A: 

When you're loading from an assembly you're instantiating the compiled object from an assembly, which is a lot different than a deserialization operation, which is what is happening with a service call. The best you can do with serialization is transfer raw XAML that can be loaded with XamlReader, but this limits what you can do with a control since you can't use any code. If you're really set on hosting controls on your server the most flexible option would be to have your app download an assembly containing the new control and dynamically load the new assembly or use a separate launcher that can download new control assemblies before starting up the main application (make sure you take the time to understand the security implications and secure the assemblies and downloads).

John Bowen
The last part of your post has me interested. How correct/common is this. I could see a scenario where the user would download the DLL in the background when he first needed a view. Has anyone else done something similar? I understand the security concerns and would obviously take the necessary precautions.
Ochowie
It's incredibly common to do this Ochowie; nearly all modern software does it. Every online MMORPG does this. Essentially, what you need to do is write a bootstrapper application that is responsible for finding and downloading program updates to your application. Once the bootstrapper has downloaded the latest updates (or been assured that there are no updates) then it launches your application.
Chris Holmes
Yeah I think this seems like the best solution I've seen to this.
Ochowie
This is basically what ClickOnce does but it's very common that you'll run into situations where ClickOnce can't quite handle deploying everything your app needs at which point you need your own updater.
John Bowen