Dual-deploying a WPF app natively and as a XBAP

2020-07-27 03:52发布

问题:

How to create a WPF application that can be deployed as either a XBAP or as a native Windows application with as little overhead as possible? XBAPs are binary compatible with WPF Windows applications and run on top of the same CLR (Unlike Silverlight). They still differ in some ways.

From deployment point of view their largest difference is that a XBAP has a Page control as the main container while a Windows application has a Window control. It would be rather trivial to make the Windows application use the Page control but I feel (Feel free to disagree) that using a Page navigation method in a Windows application is rather unintuitive.

The second major difference is that XBAPs by default are executed in a partially trusted environment. This can be bypassed though and the XBAPs can be made run in full trust mode. The partial trust mode with XBAPs means you cannot access for example remote web services or native code from the XBAPs directly.

What would be an easy and maintainable way to achieve the following with the above issues?

Requirements

  1. Deployable in both ways: as a XBAP over http and as a stand-alone WPF executable.
  2. Shows information from a remote web server such as flickr or through an unmanaged API.
  3. If possible, the deployment methods should remain faithful to their platforms. That is to say: Use Pages in XBAP where those make sense and dialogs in the Windows app where those make sense.

Restrictions

  1. Platform optimised. The stuff required by the XBAP shouldn't affect the Windows client and vice versa.
  2. The deployment options share as much code as possible. This helps in testing and maintenance.
  3. Running the XBAP should be as simple as possible. Certificate prerequirement would defeat the purpose of a XBAP.

What I have gathered is that first requirement requires two separate projects. The second restriction could be worked upon by having a user control project which contains all the UI and is referenced by the two deployment projects. A WCF web service could work around the limitations of XBAPs.

If employing a solution similar to the above lines the first restriction would require some work as the Windows client could do without the WCF service as it's already running in full trust mode. Also the third requirement would need some deployment specific code so all the UI code cannot be in the user control project.

I'd like to know what solutions could be used to resolve these problems. Feel free to ignore the partial solution. It's there mainly to explain the point and to prevent the "Thought of this already" comments. So just to clarify, I'm interested in all solutions to this problem, not just those that abide to the partial solution.

The reason for interest to this is that a solution would mean there's no need to ponder between a WPF Windows app and a XBAP as these both could be created with little more effort and the client could choose whichever suits them best.

回答1:

You may want to take a look at Prism (at codeplex) It helps to target Wpf, Xbap and Silverlight with minimum code changes (the amount of extra work depends on your project).

Here's how to use it to create Wpf and Xbap application: Prism and XBap Applications



回答2:

This scorbs article explain how to do it, and it even has an app template to do it.


(source: scorbs.com)



回答3:

I have tried several approaches to this over the years. The one that has worked best for me is to have have four projects in a single solution:

  • The main project which builds a dll containing business objects, communications, and UI.
  • The test project containing both manual and automated unit tests
  • A tiny .exe project for the Windows application
  • A tiny .xbap project

In the main project there are neither Pages nor Windows, just UserControls and custom controls. There is also a services class for displaying UI. This class is subclassed in the Windows and XBAP projects to change the way things are displayed. In each case the subclass is installed in a static property as the application starts up. All the rest of the code simply references this static property and calls methods on it. These methods perform services which differ between Windows and XBAP applications.

For example, my service class has a "ShowDialog" method that takes a FrameworkElement and shows it in dialog style, either as a Window (for Windows application) or as a Popup on a page (for XBAP).

Using this technique has allowed for approximately 98% code sharing between the Windows application and the XBAP.

My main application also has a client-server interface defined and WCF attributes applied to its data objects. There is a static property used by all code to access the service. This static property is initialized (in the class constructor) to an instance of the concrete implementation class, but the startup code in the XBAP project replaces this with a WCF client, so the XBAP runs client-server and the Windows application is actually making local calls. In each case it is exactly the same object on the server end.

Because I implemented the WCF as an interface, I was able to get away with nothing more than a simple .svc file for the WCF service end of things, and no need for separate code generation or linking in proxy/stub code.