'Binding' type does not have a matching DependencyObjectType error

by StefanOlson 30. May 2011 06:53

This is one of those blog posts so that I can easily remember what causes this particular problem.  In the Virtual Tour Viewer, I have found on occasions with .net 4.0 that if you press the back button, to go back to a previous page you get a “'Binding' type does not have a matching DependencyObjectType” exception.

As it turns out this is because I had PresentationTraceSources in the page. e.g:

OlsImage="{Binding SmallImageFile,PresentationTraceSources.TraceLevel=High}"

If you remove the reference to PresentationTraceSources  (which allows you to debug bindings), then the problem goes away!

interestingly, this exception only occurs when using the back button – if I go directly to a page there is no problem.  Weird, eh?

Tags:

WPF | Virtual Tours

Silverlight 5: does anyone at Microsoft talk to each other?

by StefanOlson 25. April 2011 12:11

The Silverlight 5 beta was made available a couple of weeks ago (http://www.silverlight.net/getstarted/silverlight-5-beta/).  Most of the features had been telegraphed in December at the Microsoft Silverlight firestarter which appeared to have been hastily organised to try and fend off criticism that Silverlight was being deprecated in favour of HTML 5.

Certainly there was, and still is some confusion as to what the purpose of Silverlight is. It was originally sold to us as a cross-platform browser independent platform.  That now seems to have changed and it is HTML 5 is the cross-platform browser independent platform.  Unfortunately the tooling to support developing HTML and JavaScript is absolutely appalling in comparison with the outstanding tools for Silverlight.

Based on this, a website that I was developing for a customer was going to have all the public parts written in HTML and the pieces where you need to login written in Silverlight.  I have now changed that and completely removed Silverlight from the project and it will all be in HTML.

So why would anyone use Silverlight? This is a good question, if you want to have a rich application that can make use of the available hardware, why wouldn’t you build a WPF application?  Well partially because WPF appears to be completely on the scrapheap. The WPF Toolkit hasn't even been updated to support visual studio 2010 and the .net 4 framework!

My previous post on LightSwitch described how they had chosen to use Silverlight rather than WPF for desktop applications.  This appears to be what Microsoft wants you to do, with continued improvements in full trust and multi-window support.

So what's new in Silverlight 5 that isn't available in WPF:

  • XAML Debugging with breakpoints for binding debugging. This looks outstanding!
  • Double (and multi) click support
  • GPU-accelerated XNA-compatible 3D and immediate-mode 2D API
  • RichTextBox overflow

But there has been no word on when or if any of these features will be available in WPF. Why is there not a new release of the WPF Toolkit with the 3-D and 2-D API available? Those of us who have invested massive amount of time in developing 3-D software using WPF (in my case for the 360° panoramas in the virtual tours) have to start from scratch, yet again!  Whilst it may be a good move to use XNA, as it is available on multiple platforms, it means that people working in both WPF in Silverlight have two different Apis to write for.

The RichTextBox overflow is completely baffling to me, why did they just not port flow documents?

There are also plenty of features already in Silverlight that are not available in WPF:

  • DeepZoom
  • Ria services - to use this you have to create a WCF service and you don't get all the advantages that you do when working with it in Silverlight
  • HyperlinkButton
  • ChildWindow
  • UriMapping

It appears from some rumours that Silverlight will be the primary programming language for Windows 8, once again suggesting that WPF has a limited future, which may be why these features have not made it into WPF.

What’s still missing from in Silverlight from WPF:

  • MultiBinding (see here for an alternative)
  • Preview events (in WPF all events such as mouse button down have a preview event that runs down the visual tree)
  • Triggers
  • FlowDocuments (see here for my attempt at FlowDocuments)
  • RoutedEvents
  • BooleanToVisibilityConverter
  • GroupBox
  • Toolbars
  • Expander
  • Commanding infrastructure
  • Default set of brushes
  • Many ToolTip options
  • I'm sure there are more than I have missed.

All of these make developing Silverlight a lot harder and you often find yourself hacking around the lack of these features.  I have built a library to try and ease this, but you are forced to have separate xaml between the two targets because there are so many things not available in both.

To top this off, there is a new release of Silverlight for the Windows phone, but that is only Silverlight 4!

If, like me you are building an application for WPF, Silverlight and Windows Phone, this just makes life incredibly difficult because across all three platforms there are features that are available in completely different ways! 

One wonders why people at Microsoft don't sit down and talk to each other and try and make these things simpler for developers, especially since some developers are likely to abandon WPF because of the complexity of trying to manage Silverlight and WPF development, or developers like me will abandon Silverlight development for public facing websites.

There are certainly some good new features in Silverlight 5, but I hope that the various teams at Microsoft will start talking to each other and create a more cohesive development platform.  With Google already way ahead on the phone market and wanting to get into the operating system market Microsoft really have to up their game.

Tags:

Silverlight | WPF

Is this the beginning of the end for WPF?

by StefanOlson 4. August 2010 07:16

Microsoft yesterday announced a new product, called LightSwitch, which is a new Visual Studio-based IDE to rapidly develop applications. You can see a very impressive demonstration here:

http://channel9.msdn.com/posts/Dan/Jay-Schmelzer-Introducing-Visual-Studio-LightSwitch/

Looks like there's some very nice controls (for handling phone numbers etc.) in there, hopefully they will be made available outside of that product.

What is particularly interesting about this is that they are producing a Windows application, which is not using WPF. They have chosen to use Silverlight  running out of browser. This is bad for WPF, because that is what you would expect to be used on the Windows platform.  It suggests that over time WPF will be replaced by Silverlight, even on Windows.

So why have they chosen Silverlight? I guess there is some advantages in allowing organizations to be able  run the application on the web.  Hopefully, the reason for that decision will become clearer over time.

What I would've done is built the two desktop targets using WPF. However, what the Microsoft development team would've found is that it's almost impossible to share xaml code between WPF and Silverlight, so they would quickly given up and gone the Silverlight only route.

Hopefully Microsoft can improve the developer experience when single sourcing WPF and Silverlight, but there's still a long way to go.

….Stefan

Tags:

Silverlight | WPF

Workaround for low-quality bitmap resizing in WPF 4

by StefanOlson 20. July 2010 09:55

As many people have already discovered Microsoft made a change in the.net framework resulting in the quality of bitmap scaling being reduced by default.  This is because the default mode is now low quality, rather than high-quality.  Optionally you can go back to the way it was previously, but this requires you to turn this feature on. 

It is very disappointing that Microsoft have chosen to break backwards compatibility in this way. Apparently it was to help some customers to were experiencing slow image scaling. Why they were not just told to set the default to low quality image scaling, rather than forcing everyone in this mode is beyond me! In another similar situation they specifically didn't change the default font scaling mode, designed to increase text quality because it would break existing applications. Why they did not apply the same theory to this feature is confusing at the least.

Details of the changes are here:.

Crappy Image Resizing in WPF? Try RenderOptions.BitmapScalingMode

I have found the best way to ensure that this feature used throughout a program is to set the default scaling mode in the window constructor:

public MainWindow()
{
    InitializeComponent();

    RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.);
}

However, this does not deal with a situation where you need to use RenderTargetBitmap, for which this setting does not apply.  You might use RenderTargetBitmap in a situation where you want to resize an image, something like this:

RenderTargetBitmap result = new RenderTargetBitmap(newWidth, newHeight, 96, 96, PixelFormats.Default);

DrawingVisual vis = new DrawingVisual();
using (DrawingContext dc = vis.RenderOpen())
    dc.DrawImage(Image, new Rect(0, 0, newWidth, newHeight));

result.Render(vis);

So obviously you would probably try and do this:

RenderOptions.SetBitmapScalingMode(vis, BitmapScalingMode.HighQuality);

Which would do nothing.  Unfortunately, Microsoft's support of this particular problem has been extremely poor with no responses in newsgroups or in comments on blogs. I e-mailed Pete Brown, and received no response.

As it turns out, thankfully there is a workaround. You just need to recode,using a DrawingGroup (I found the solution here: http://xiu.shoeke.com/2010/07/15/resizing-images-with-wpf-4-0/) and set the attached property on the DrawingGroup. e.g:

RenderTargetBitmap result = new RenderTargetBitmap(newWidth, newHeight, 96, 96, PixelFormats.Default);

var group = new DrawingGroup();  

RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
group.Children.Add(new ImageDrawing(Image, new Rect(0, 0, newWidth, newHeight)));  

DrawingVisual vis = new DrawingVisual();
using (var drawingContext = vis.RenderOpen())  
    drawingContext.DrawDrawing(group);  

result.Render(vis);

Which does result in a large amount of additional unnecessary code, but at least it is still possible for your application to work in WPF 4!

….Stefan

Tags:

WPF

Virtual Tour Viewer available for Silverlight!

by StefanOlson 23. September 2009 08:22

image

ComponentArt are currently holding a competition to find the best Silverlight application. The community can vote for their favourite application and they will then be judged by some of the most respected people in the Silverlight community.  The winner gets $10,000 US!  You can see and vote for all entrants here:
http://www.componentart.com/community/competition2009/

Over the past couple of weeks I've spent a lot of time redesigning the Virtual Tour viewer I have described in previous posts.  It's not yet perfect, but it is an improvement on the previous releases. Having redesigned the WPF version, I have ported those changes across to the Silverlight version and have entered in the competition.    There is still some work to do removing a few bugs before the official judging starts on 23 October.

You can find (and vote for) my entry here:
http://www.componentart.com/community/competition2009/details.aspx?id=1109

The competition entry includes the full Versailles Virtual Tour. We are trying to see if people will be willing to donate to help improve the tours, because it will give greater access for a larger number of people.

As I've discussed in previous posts, the Silverlight version makes use of the Silverlight WPF compatibility library that I have built, which provides Silverlight versions of routed commands, flow documents and a number of other features not found in Silverlight.  The WPF version of the Silverlight compatibility library includes features such as the URI mapper and child window.

As an incentive to encourage you to vote for the virtual tour, I will release the Silverlight WPF compatibility library on codeplex, if I win the competition.  The reason for this is the competition provides a substantial financial prize for the winner, and it would give me some additional time to be able to complete the code and samples.  The more five-star votes I get, the more likely I am to win, so please go and vote!!

If you have feedback on the tour we'd love to hear from you either via e-mail or via the comments.

…Stefan

Tags:

Virtual Tours | Silverlight | WPF

Silverlight multi-binding for WPF

by StefanOlson 21. July 2009 10:42

In my previous post on Silverlight multi-binding support I mentioned that theoretically it should be possible to use the Silverlight multi-bindings in WPF. Unfortunately the practicalities of single sourcing between WPF and Silverlight are not always as simple as you might expect, and this case was no different!

Given that WPF already has its own multi-binding functionality, why would you want to use the Silverlight attack? You only really want to do this when you want to have source code compatibility between WPF and Silverlight. The updated source code for the Silverlight multi-bindings, which is available below demonstrates this with an application that uses the same source code for both WPF and Silverlight.

So onto the difficulties in making it work for WPF. The first problem is that Colin’s original structure used an ObservableCollection for the bindings:

<local:MultiBinding TargetProperty="Text" Converter="{StaticResource TitleConverter}">
    <Binding Path="Surname"/>                            
    <Binding Path="Forename"/>
</local:MultiBinding>

Unfortunately,WPF will not let you put bindings into an ObservableCollection, so I had to build a new BindingCollection class based on the model used by multi-bindings in WPF.

Once that was solved the larger problem was the fact that objects are created differently from the Xaml/Baml between Silverlight and WPF. This meant the assumptions about the timing of the creation and the completeness of an object at any given time were wrong.  WPF’s Baml reader will create an object, assign it to a dependency property and then fill its attributes. Silverlight’s Xaml reader will create an object, fill it’s attributes and then assign it to the dependency property, a feature the Colin was relying on.

So I had to come up with a completely different solution. What I decided to do was catch the loaded event of the object that we are connected to and at that time I convert the bindings that we have created in to pure WPF multi-bindings as you can see in the code below:

#if !SILVERLIGHT
void Loaded(object sender, RoutedEventArgs e)
{
    _targetElement.Loaded -= Loaded;
    foreach (MultiBinding binding in Bindings)
    {
        FieldInfo field = _targetElement.GetType().GetField(binding.TargetProperty + "Property",
                                                            BindingFlags.Public | BindingFlags.Static |
                                                            BindingFlags.FlattenHierarchy);
        if (field == null) continue;

        System.Windows.Data.MultiBinding newBinding = new System.Windows.Data.MultiBinding
                                                          {
                                                              Converter = binding.Converter,
                                                              ConverterParameter = binding.ConverterParameter
                                                          };
        foreach (BindingBase bindingBase in binding.Bindings)
        {
            newBinding.Bindings.Add(bindingBase);
        }
        
        DependencyProperty dp = (DependencyProperty)field.GetValue(_targetElement);

        BindingOperations.SetBinding(_targetElement, dp, newBinding);
    }
}
#endif

The only tricky part is finding the dependency property that we need to work with - This is a bit of a hack where I search for a static field with the given name and Property appended to it, which is the naming convention for dependency properties.

Using the multi-bindings is still exactly the same as described in the previous post but can now be used on both WPF and Silverlight!

Download Source

you can download the latest source code from here

…Stefan

Tags:

Silverlight | WPF

Issues with the Silverlight Navigation architecture

by StefanOlson 3. June 2009 15:56

In my last post, I described some of the ways I was able to use the Silverlight URI mapping architecture to provide more customized routing.

However, there are a few problems with the navigation/URI mapping architecture that I haven't been able to find ways to work around.

Setting a title

One of the major problems I've encountered is getting the title (in the browser's title bar) to be set. There is a field in the Page class called title. So you would think would be relatively simple. It appears that there's some difficulty in setting the page title, unless it's set at a particular time during the navigation. Here's how I try and set it:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    CachedCategory category = ClientStaticCache.GetCategoryById(
int.Parse(NavigationContext.QueryString["categoryid"])); Title = category.Name + " - " + "my site"; }

 

But the title never appears -  the URI Appears as the title. I started a thread on the Silverlight forum, but no one has been able to give me an answer as to when you can set the title so that it appears correctly in the title bar and the navigation history of the browser.

When you're working in an asynchronous world you often won't get the title at the time the navigation starts, there needs to be a way to set the title when the data has come down the line.

Asynchronous operation

If I want to go and just find out if a particular URI exists (e.g: a category), before navigating to it, I either have to have a cache of categories on my local Silverlight client, which is what I'm doing at the moment, or you need to go to the server and verify that that is a valid category. The problem with the URI mapping architecture is that it is synchronous, so it is not possible to go and ask the server and then come back to the URI mapper and say yes, this is where I want to go.

Null return from the URI mapper causes exception

As described in my previous post, if you return null from the URI mapper because you've handled the URI by displaying a dialog or something like that, an exception is caused. However, the exception doesn't happen if you change the URI in the address bar, only if you call it via Frame.Navigate.

Bug on connect

Reusing a page

Another scenario occurs when we have we have content on a page which is very slow to load. In my case the Virtual Tour Viewer has a page that contains floor plans. These are very slow to load, and I don't want to have to reload the floor plans as the page changes, because some pages display the floor plans and others don't.

Ideally, the Frame system would be able to come to you and say here's a page I'm asking for, would you like to give me the page. In this case, I could reuse the pages containing the floor plan and increase the speed of the application simply by handling an event on the frame.  e.g:

Page Frame_GetPageForUri(object sender, GetPageForUriEventArgs e)
{
    if (e.Uri.ToString() == "categorycontrol.xaml")
    {
        return CategoryControl;
    }
    return null;
}

private Page _CategoryControl;

private Page CategoryControl
{
    get
    {
        if (_CategoryControl == null)
        {
            _CategoryControl = new CategoryControl();
        }
        return _CategoryControl;
    }
}

The way I am looking to do this currently is to store the floor plan control outside of the page so that it doesn't get destroyed if the garbage collector tries to clean up when the page isn't displayed, but that is not very satisfactory.

Role-based pages

Another useful piece of the navigation architecture would be the ability to use an attribute to declare the required roles to display a particular page. If the user does not have that role, then a login dialog would be displayed, in the same way as is done with the ASP.net authentication system. Under Silverlight, you could do this in the same way as is done on domain service you have a requires authentication attribute and a requires role attribute:

[RequiresAuthentication]
public partial class CategoryPage : Page

WPF compatibility

The virtual tour viewer needs to work on both WPF and Silverlight. I've encountered a number of problems trying to share the code between WPF and Silverlight with regard to the navigation framework.  WPF 4 currently doesn't have the API improvements that have been made to the Silverlight navigation framework such as the URI mapper and a number of virtual functions in the page class.  This means I have had to create a whole set of classes just to create a level of compatibility, part of which is completely impossible because of the lack of the URI mapper!

It's not clear at this stage of this will be fixed by Beta 2 of the .net framework 4.

Overall the Silverlight navigation API is pretty good,  Hopefully some minor tweaks will make it a huge amount better.

Tags:

Silverlight | WPF

Virtual Tour Viewer beta available

by StefanOlson 17. February 2009 16:57

tourwpf

I'm sorry it has taken so long, but the beta version of the virtual tour viewer for WPF is now available.  It demonstrates the splash screen that we have developed along with targeted commands, the Silverlight WPF library and the WPF panorama library we have written.  To download the tours, click here.  The available tours are all evaluation versions, the full versions can be purchased from our website www.palacevirtualtours.com

It has taken longer than expected because we have been busy working on our core product, HyperText Studio, a WYSIWYG help authoring tool. We are finishing version 5.1 which supports Windows Vista and Windows 7.

I would love to make the Silverlight version of the virtual tour viewer available, but unfortunately I have been unable to find an affordable tool to provide obfuscation functionality for Silverlight.  For the WPF product we use .net reactor (http://www.eziriz.com/) but they don't have a Silverlight compatible version yet.  I suspect one may not be too far away as there are references to version 4 of .net reactor on their website.  If anyone knows of an affordable tool for doing obfuscation for Silverlight, please let me know.  As soon as I can get an obfuscator that works I will make the Silverlight version available so people can see it for themselves.

We are continuing to work on preparing the Silverlight WPF library and targeted commands for release.  Unfortunately it is quite a big job to prepare the demo application, so I'm not sure what the timeframe will be.

The panoramas are only available in the Buckingham Palace and Windsor Castle tours (in the Grand Staircase room in both tours).  They use the panoramas that were released on the royal web site on Friday.  If an Internet connection is available, the panorama is downloaded from the Internet and made available in the tour.

The virtual tour viewer uses a slightly updated version of the splash screen code that we have previously made available.  I will be adding that update to the splash screen page in the next couple of days.

We'd love to your feedback on the virtual tour viewer, feel free to contact us via the comments on this page or via e-mail.

If there are things you see in the tour that you would like an explanation on how we implemented it, please let me know.

If you have not installed the .net framework 3.5 on your computer the installer will attempt to download the appropriate files from our website to install it on your machine.  However because InstallAware, the maker of the installation program we use do not provide 64 bit versions of the framework, it will not be able to install the framework on vista or x64 windows 7 x64, so in this case it is a substantially better idea if you're able to install the .net framework before installing the demos.  If anyone knows of an installer that does provide x64 versions of the framework installer (and better support!), please let me know.

Known issues in the WPF Virtual Tour Viewer

Because of the complexity of fixing these issues, it's very unlikely these will be fixed before the release, apart from the icon.

  • The mouse wheel doesn’t work correctly on the picture control
  • Clicking on the Search button in the description tab will display the find box, but you are not able to put the focus in the text box. This may be a .net framework bug, but I haven’t yet investigated
  • It is not possible to see either the caret or the selection in the find box on the main toolbar. Unfortunately the .net framework doesn’t allow you to customize either of these settings so I will have to write my own textbox from scratch (or hopefully this will be fixed in the .net framework 4.0)
  • The icon needs to be redesigned
  • Printing a description currently produces a blank page.

Download links

Buckingham Palace Virtual Tour (48Mb)

Windsor Castle Virtual Tour (32mb)

Versailles Virtual Tour (59mb)

…Stefan

Tags:

Virtual Tours | WPF | Silverlight

A better WPF splash screen

by StefanOlson 27. November 2008 10:07

Further Update: there was a bug relating to the splash screen start application not correctly closing. This has now been fixed and you can download it here

Update: Thanks to all of those who have pointed out that it didn't work correctly on windows XP, I have now fixed this and you can download it here

WPF 3.5 Service Pack 1 introduced a new splash screen feature which was supposed to provide a splash screen whilst the program loads.  Unfortunately it has a number of faults:

  1. Although the splash screen class uses native code within it, it is actually part of the .net framework so a large part of the framework has to load before the splash screen can be displayed.  This still provides a substantial period of time, particularly on cold boots where the user doesn't have any indication that your application is loading.
  2. The splash screen will display images stored in resources in either an application or a dll.  In my application I need to load the splash screen from an image at runtime.  I have submitted a suggestion on connect that this feature should be added.
  3. There is a bug in the splash screen code, that in certain cases where a user may shift focus away from the splash screen, the splash screen will throw an exception causing the application to crash.  I have submitted this issue as a bug on connect, but Microsoft seem to have ignored my attempts to reopen it, so it is anyone's guess it will be fixed in the update to the service pack due early next year
  4. Because it is not set to be on top, the splash screen can disappear below your application.
The last three issues could have been avoided, had the splash screen been part of the beta of the service pack.  It was not available until the final release, so we were unable to comment on these issues or even discover them prior to that.

Recently, Bradley Grainger on the Logos Bible Software Code Blog posted a series on how to build a splash screen in native code.  His solution is to build an executable which displays the splash screen using native code and then runs your WPF application.  This resolves problem number one because it starts much more quickly than the .net framework and makes it clear to the user what is going on.  Of course it also resolves problem number 3 because it doesn't have the same code is .net is using.  However it does not address problem number 2, and his code was posted without a compilable version, he just posted snippets of code in his blog.

Since I needed to solve my splash screen problems, I built Bradley’s code into a new Visual C++ application and made a few improvements including being able to display images not in the resources, being always on top, and fading out the splash screen like WPF does when it no longer needs to be displayed.

The source code can be downloaded here

The code is available under the same licence as the original.

To test it for yourself, after you have downloaded the code, run splashscreenstarter.exe in the root folder.  If you want to see how it works in a real world application, this video shows you how we use it in our virtual tour viewer.

So, if you wish to use it in your own application, what do you do?  You can modify the splashscreenstarter project.  Generally you should only need to change this line of code in splashscreenstarter.cpp:

CSplashScreen splash(
        hInstance, 
        // Length of time in milliseconds to display splashscreen fading 
        3000, 
        // Specifies the way to load the image for the splashscreen 
        // To load from the resources, as we have done here, provide the 
        // resource name and the resource type name.  We have used a jpg.
        // If you use a PNG, its opacity should be honored to allow you 
        // to display partially transparent splashscreens.
        // To edit the resources in a C++ application go to the resource 
        // view tab
        // To load from a file use this line instead, where filename is the file
        // you wish to load:
        // new CFileImageLoader(filename), 
        new CResourceImageLoader(MAKEINTRESOURCE(IDR_SPLASH), _T("JPG")),
        // Application prefix.  This will be added to the event name so there are no 
        // conflicts between applications.
        _T("SplashScreenStarter"), 
        // File name of your executable to run.  The extension does not need to be .exe.  
        // If you want to stop your users from starting your application without displaying
        // the splashscreen you could use a different extension.
        // Is assumed it is in the same folder as this program 
        // If it is not you can call splash.SetFullPath
        _T("SplashScreenTester.exe") 
        ) ;

You will need to replace the image used for the splashscreen which is stored in startuppic.jpg.  You'll also want to replace the icon with the application icon you are using.

Then in your WPF application class (app.xaml.cs):

protected override void OnStartup(StartupEventArgs e)
{
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Loaded,
        (DispatcherOperationCallback)delegate { CloseSplashScreen(); return null; },
        this);
    base.OnStartup(e);
}

private void CloseSplashScreen()
{
    // signal the native process (that launched us) to close the splash screen
    using (var closeSplashEvent = new EventWaitHandle(false,
        EventResetMode.ManualReset, "CloseSplashScreenEventSplashScreenStarter"))
    {
        closeSplashEvent.Set();
    } 
}

Notes that the event name, CloseSplashScreenEventSplashScreenStarter, includes the prefix from above at the end of it.  If you use a different prefix you will need to modify this.

If you wish to close the splash screen at any each time without fading it you can call this code:

static protected void CloseSplashScreenWithoutFade()
{
    // signal the native process (that launched us) to close the splash screen
    using (var closeSplashEvent = new EventWaitHandle(false, 
        EventResetMode.ManualReset, "CloseSplashScreenWithoutFadeEventSplashScreenStarter"))
    {
        closeSplashEvent.Set();
    }
}

Hopefully this code will help you to create a more responsive application. If you have any questions or comments, please feel free to contact me.

…Stefan

Tags:

WPF

Single Sourcing WPF and Silverlight

by StefanOlson 27. November 2008 07:32

If you are like me, when you first heard about Silverlight, you thought this is fantastic, the WPF application you just developed can be taken, and with a few changes to support asynchronous loading, you've got an Internet accessible application! Well, think again!  That's not how it works.  Although it is supposed to be a subset of WPF, there is a lot of core WPF functionality that is either not there or operates fundamentally differently under Silverlight.

Most Microsoft people recommend that if you are starting a new application that you develop the Silverlight version first, and later move that to WPF.  Unfortunately, in our case we had already developed the Virtual Tour Viewer software for WPF, well before Silverlight was on the scene.  To some extent I still think it's better start with WPF because ultimately, hopefully, Silverlight will pick up more WPF functionality, and in my opinion the WPF functionality, such as triggers, is generally easier to code with than Silverlight equivalents.

To prove that it is possible, below are images of our virtual tour viewer running in WPF and Silverlight:

WPF

Silverlight

wpftour sltour

So, having built your application how do you convert it to Silverlight?  Well, the first thing is to create a new solution.  I have one solution for the Silverlight version and another one for the WPF version.  So I ended up with a folder structure like this:

 tourfolders

The Virtual Tour Viewer folder is the WPF version.  Within each solution the projects are replicated, with Silverlight versions and WPF versions of the project (where appropriate, there is some projects that are only in WPF in the Virtual Tour Viewer).  This can be seen below:

WPF

Silverlight

wpfprojects slprojects

So, what code can you share between Silverlight and WPF?  Initially, I was hopeful of being able to share both the xaml and .cs files.  However it became clear very early on that it was not going to be possible due to the number of differences in the xaml capabilities between Silverlight and WPF.  In the end there was not a single XAML file that I was able to share.  A number of people have also reported difficulties in dealing with linked XAML files in Visual Studio, although in my testing I did manage to get it to work, but I didn't do any serious testing so that may have been a fluke.

So in the end I share the code behind .cs files but not the XAML files.  I am also able to share all the data access layer .cs files.

The one important point is that you need to make sure that each assembly has exactly the same name on WPF and Silverlight.  This is important for xaml references

e.g:

xmlns:Controls1="clr-namespace:OlsonSoftware.Windows.Controls;assembly=OlsClassLibUI"

This reference can then be used across both WPF and Silverlight if the assembly name is kept the same. This can be done by right clicking on the project and selecting properties:

assemblyname

There are two ways you can manage each project:

Both projects in a single folder

This is the simplest way.  All you do is create a second project (in my case a Silverlight class library), in the same folder.  Visual Studio automatically sees all the files in that folder and you can simply exclude or include any files to get the files you require. 

incinprj

A problem with this approach is that it doesn't work where you have custom controls.  The xaml for a custom control is stored in a file called themes/generic.xaml.  Because your xaml will almost inevitably be different between WPF and Silverlight, it isn't possible to share that file between the two projects when they are both in the same folder, as you need two separate generic.xaml files. 

Another problem is that both the WPF and Silverlight solution want to build the same folder, e.g. Debug.  The work around for this to set the output path in the project properties:

outputfolder

Projects in separate folders using linked files

This is the way that I ended up choosing for almost every project in the solution.  It gives much more flexibility the previous option, because I can now have a clear separation between files that are just used for Silverlight and the WPF project.

So, how do you do this?  Well this time you create a new class library project in a new folder.  This leaves you with an empty project.  Now you have two projects, one for Silverlight and one for WPF, each in their own folder.

For any files that you need to share, you can use Visual Studio's Add Existing Item.  The difference is that instead of clicking Add, you click the drop down menu beside it and Add as Link:

addaslink

Normally, Visual Studio will copy the file to your project folder.  Using this feature it does not do this and simply references the file in the other folder.  This way any changes you make for the other project are automatically reflected in this one.

This opens up another problem, there are a number of features available only in WPF, or in Silverlight that you may wish to use.  With this linked file, if you use any of these features it may not compile in both projects.  The solution to this is to use the conditional compiling feature.  Any code that does not compile in Silverlight can be surrounded by these commands:

#if !SILVERLIGHT
[code goes here]
#endif

Of course it is the opposite situation where the code does not compile in WPF:

#if SILVERLIGHT
[code goes here]
#endif  

Unfortunately you'll find yourself using these far more than you would wish because there are so many differences between WPF and Silverlight.  I have resolved some of these issues by developing a WPF compatibility library to provide WPF functionality on Silverlight such as routed commands, routed events, FlowDocumentViewer, navigation etc.  We will be making it available as an open source library in the near future.

With this project setup or you can add files specific to Silverlight and WPF in their respective project folders as normal.

Sharing user controls

To share the code behind for your xaml files, create your user controls as normal in WPF.  e.g:

wpfctl

Then create the same control in Silverlight and delete the .cs file from the project.  Then you can add the existing CS file from the other project.  Unfortunately, when you are using linked files as code behind, Visual Studio doesn't display them as a child of the xaml file, even though it is correctly indicated in the project. So this is what you will end up with:

slctl

To share the xaml code between both projects you just have to copy and paste, unfortunately.

Sharing custom controls

Custom controls have a single xaml file themes/generic.xaml.  You need a separate file in both the WPF and Silverlight projects.  The code for each control can be linked to as described above.

 

So that is an overview of how we solved project management with Silverlight and WPF.  We hope that it is helpful and adequately explains how we have done this.

If you want to check out the WPF and Silverlight versions of the Virtual Tour Viewer, I'll be posting a new blog entry when I make them publicly available in the next week or so.

…Stefan

Tags:

WPF | Silverlight

About the author

Stefan Olson is the Managing Director of Olson Software.  He has been developing software using Microsoft Technologies for nearly 20 years.

He is currently working on building the next generation Virtual Tour software in WPF and Silverlight for www.palacevirtualtours.com.