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
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).
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.
Related
This is a question about design approach. I have limited COM experience and a little WCF experience. My constraints are given by the application environment, but I have some design flexibility.
From within a VB6 dll, I need to start, and communicate with, a WPF application. The WPF application is currently an exe, but I could make it a library if that helped. I would like to provide two way communication between the VB6 dll and the WPF application. I have some flexability to adjust the design of the VB6 dll.
I'm developing C# using in VS2010 and .NET 4.
How many components should I use? Can I start the WPF application In-Proc with the VB6 dll? Should there be a third component between them? Can COM+ play a helpful role? Do I have to make the entire WPF application COM-visible? Is there a down-side to doing this?
I'm looking for a design approach that I can prototype. I'm willing to research the details.
I would
Create a Web Service from the WPF application, using WCF. I would abstract out those aspects of the WPF application which should be accessed remotely. This would explicitly not include any of the user interface code.
I would create a simple class library project, and use "Add Service Reference" to add a reference to the WCF service.
I would make the methods of the class library COM-visible
I would call those methods from VB6
This has the benefit of removing any considerations of user interface from the equation.
Out of the options available I like the COM option more than the 'start another process' option for the simplicity that the inter 'application' communication will be via method calls rather than WCF or anything similar.
I am assuming that your VB DLL lives in a window'd process and not a service or web application. You would only need to mark any exposed types as COM visible, that is the classes, their argument and return types.
You may have to wrap your WPF UI inside the windows forms ElementHost [1] but I'm not sure, try it and see.
I'm not sure if you saw this [2] in your search, it sounds do-able but unsupported, ok as long as you don't have too much going on.
[1] http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx
[2] http://social.msdn.microsoft.com/forums/en-US/wpf/thread/7555ba6a-1359-4dfe-aa23-c31a8f121142/
I work on an application primarily written in VB6 but most of the recent code is written in .net with UI components built in WPF and some WinForms. Datasources for this application are WCF, MSSQL server, and a propritary unix based server. All the WCF calls are made from data access components referenced by the .net UI components.
You can host WPF in VB6 windows or other container controls. Start by getting the Interop Forms Toolkit and build shell user controls to host your WPF controls.
To be able to host WPF in these controls you need to build a WinForms usercontrol which contains a ElementHost, which you can set the content to your WPF usercontrol.
WPF Usercontrol inside an Element Host inside a
WinForms usercontrol inside a VB6 usercontrol or
window
The interop toolkit will want to build VB.Net code but you can do it in C#, although I have not tried this. The usercontrols created by the interop toolkit will be exposed as COM components which you can reference VB6 by adding them as components via Project > Components and then you will find them in the toolbox.
In terms of data sources (WCF, databases) etc, you should build all your data access in .net components referenced directly from the UI components, don't try to call back in to VB6 libraries, you will probably just create a mess.
In my application I also have a configuration section which I call from the VB6 application startup which sets up an IoC container for all the .net components.
From a best practice approach I actually would recommend rewriting your VB6 code to .net and putting VB6 out of the picture. If this is not an option then you have a number of options, my explanation is just one of them.
I tried to serialize a FrameworkElement with DavidPoll's XamlSerializer, but I get a totally different result than the (right) one that I get with Silverlight Spy. For example with XamlSerializer I get alot of empty tags(like MatrixTransform, ScrollViewer etc.) but not the ContentPresenter node that I get with Silverlight Spy. Any idea how to get a clean logical tree at runtime?
Update: I have a form designer program that stores those forms in a DB and at runtime it creates objects (user controls) from that info stored in a DB. Each form is composed of some fields. At runtime it programmatically creats an UserControl that contains all fields. I would like to get the generated XAML, just like I can get it with Silverlight Spy.
edit: I'm not limited to Silverlight environment, a soltion for a desktop application is valid too.
Short answer is: I don't think you can from within Silverlight itself. Sorry.
Once the XAML has been parsed and loaded into framework elements you have already lost information. For instance regenerating a path from the in memory object is non-trivial and you won't have access to the internals of the path element from Silverlight code.
Silverlight Spy adds back information that a simple XamlSerializer won't generate. Silverlight Spy has no limitations as it is a "real" desktop application, with full operating system access, whereas you want to actually do this in Silverlight itself which is very restricted sandbox environment (for security reasons).
I've created a WCF RIA Service that I'd like to use with a WPF application. I've added several System.ComponentModel.DataAnnotations validation rules on the entities meta-data, all which work great on the server when I call .SubmitChanges(changeSet) from the client. I'd also like to validate my entities on the client side before I sumbit my changes to the server but I have no idea how to do so. Any help in this regard would be greatly appreciated! Thanks....
As far as I know, there is no WCF RIA Services for WPF (although I'd be glad to be proven wrong, as I am waiting for this...), so you have to do the client-side work yourself.
Use the VisualTreeHelper to go over every control in your form, and recursively if the control is a panel. For each control, have a list of potentially-bound properties (I guess there is only one in this case). For example, a TextBox will potentially have its TextBoxProperty bound, a CheckBox will have its IsCheckedProperty bound. Use BindingOperation.GetBinding to get a Binding instance, which gives you the Source and Path properties. Now use reflection on the source to see if there is a data annotation associated with it. If there is, check it.
Yes, it is a lot of code.
I want to know about general methods to dynamically load content into your silverlight application.
More specifically, I want to create something like a widget-based application, where all GUI objects are small independent widgets. I want to provide a static chrome, like a frame, hosting the actual widget, that is loaded from an extern source like a website or is uploaded by the user and is shown in this frame.
The questions are:
What does the widget author specifically have to provide, in order for me to load his widget application into my application? I imagine I have to query the provided DLL for something like a ViewModel and its DataTemplate, a UserControl or even a XAP File. What would be the best way? The external widget should also implement a certain interface, so that the outer application can call methods like Loaded and Unloaded on it.
Small code samples would be appreciated.
What about security? How do I prevent the inner widget application to access my outer application. I think the widget app could go up the control tree or access the DataContext of my frame control, hosting the application. Is this an issue? If so, how to solve it?
Thanks in advance!
Andrej
You can dynamically load controls from dlls that your widget authors could provide, MS's Mike Taulty's done a walkthrough.
Microsoft also have Prism which allows you to break up your silverlight code in a modular fashion. I haven't tried it yet to see if it's suitable for loading individual controls, but my impressions of what I've read about it seem to indicate it has a framework for doing that.
As for security, they would have access to the rest of the application, so perhaps this isn't suitable.
We are looking at creating a WPF UI that runs across multiple AppDomains. One of the app domains would run the application while the remaining AppDomains would host a series of user controls and logic. The idea, of course, is to sandbox these User Controls and the logic away from the main application.
Here is an example of doing this using MAF/System.AddIn. What are some of the experiences other have had with this? How does this solution handle RoutedEvents/Commands that might occur inside one user control and do these get properly serialized across AppDomains? What about WPF resources? Can they be accessed across AppDomains seamlessly?
Old question, but nonetheless: You will need to have multiple UI threads - one per AppDomain. Create them like this:
var thread = new Thread(() =>
{
var app = new Application();
app.Run();
});
thread.Name = AppDomain.CurrentDomain.FriendlyName;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
The biggest challenge is then that you cannot send FrameworkElements between AppDomains (they are not MarshalByRefObject), but you can use the FrameworkElementAdapters.ViewToContractAdapter() and ContractAdapterToView() methods to work around this limitation. See the FrameworkElementAdapters MSDN page for more details.
Then, once you have this in place, the biggest problem IMHO is that you cannot lay anything on top of the FrameworkElement from the "remote" domain (the classical "airspace problem"). See this thread for more info about this.
I answered a simular question here and edited it for WPF also, you can use an intersting property of how the compisition engine operate's to tail-coat a dispatcher Pump, into one of the rendering contexts. It's a really light weight option.
Also, I'm guessing you know about the enterprise library and unity?
There is a WPF application block so using that pattern is not too painful ;) But don't they say, no pain no gain?
There's also CAB (Composite UI Application Block), ties into unity. The WPF SDK folks have crafted a Silverlight & WPF platform. (a.k.a Prism).
Oh right, also, you asked about Resources? I prefer to load reasources manually in the Application class. One thing I've realized, say you have a ResourceDictionary in a sub-folder and you are loading up MergedDictionaries in that ResourceDictionary. So, if in your Application class, you load "my-res-dir/MergedDictionaryLoader.xaml" (by code or xaml), ALL FUTURE LOADS OF MERGEDDICTIONARIES ARE LOADED FROM "my-res-dir".
Sort of insane if you ask me, I would think that as the process current directory has not changed, you should specify "my-res-dir/foo.xaml" for all your additional directories. However this is not the case (I do not believe this is documented anywhere at least very well and should be considered a bug imho).
So remember, WPF resource dictionary loading is going to be based off of the directory from which the current XAML is in. So you specify Source="foo.xaml" from within your "my-res-dir/MergedDictionaryLoader.xaml". I've even played with the URI pack / absolute syntax, however I've never found that too be much more intuative.