Registering a custom URI protocol to handle custom resource loading from XAML - wpf

I'm working on a project where loose bits of XAML (and some associated IronPython code) will be dynamically loaded and executed by a client application. The client will be using a custom WCF service (and some local caching) to retrieve the XAML, backing scripts, and related resources (icons, images, etc..).
I would like to register a custom URI protocol/scheme to make it easier for the developers of the dynamic packages to reference their resources, like the following:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="custom://MyPackage/Icons.xaml" />
<ResourceDictionary Source="custom://MyPackage/Styles.xaml" />
<!-- ^^^^^^ -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
</UserControl>
As far as I can tell, I can derive a custom UriParser and register it, but that only seems to be half the battle. The remaining work is to provide whatever component is necessary to resolve the custom URI and retrieve the required content.
Is it possible to provide or override functionality in WPF to allow it to call my custom data service when one of my custom URIs is encountered? Or, if this is impossible, is there any sort of alternative?

From what I understand, you need to create a class that derives from WebRequest and register it with WebRequest.RegisterPrefix.

As an alternative, I wonder if you could create a new class that inherits from ResourceDictionary (since it is not sealed) and provide a new definition for Source. This would let you intercept the value being set to Source then and run it against your custom UriParser. This would also allow you to easily update the ResourceDictionary with the results.

Related

Shared WPF resources inside an activity designer library

I'm developing a bunch of custom activity designers, which contain custom controls, images, styles etc. The designer XAMLs are spread over several subdirectories in a library project (not a WPF application, therefore no app.xaml available)
I need a central place to store resources, just like the app.xaml in a regular WPF application.
Currently I use a projectdir\Properties\lib.xaml file like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="TrafficLight">
...
</ControlTemplate>
</ResourceDictionary>
And reference this from all my designer XAMLs like this:
<sap:ActivityDesigner.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/ActDesLib;component/Properties/lib.xaml" />
</ResourceDictionary.MergedDictionaries>
where ActDesLib is the name of my assembly.
This does work, but it looks a bit clumsy. Is there a better way to do it?
Is there some "magic" app.xaml-like file that gets included automatically for a library project, without the need to add any special markup to the individual XAML files? That would make it so much easier to enforce a consistent style, even with multiple developers working on the different designers.
BTW: I tried to use relative pathes in the Source="..." attribute. This did not work when using my activities in a workflow inside VS2010, it could not find the resources then. With the absolute path, containing assembly name, it works fine. But is there no way that VS2010 or a rehosted designer can find out the path to the resource dictionary file automatically, with only relative references inside my XAMLs?

WPF Adding a 'Resource' Project to a solution with multiple WPF applications

I am developing three kiosk-like applications in WPF. They will share a similar look and feel, and I was hoping to create the projects all in the same solution. What I would like to do is add a project to the solution that just holds shared resources, such as fonts and images.
My question is, is it possible to share resources like embedded fonts across applications, and if so, what is the appropriate project type for this use? (class library? WPF user control?)
I would create a WPF Custom Control Library, then create a ResourceDictionary to hold the resources, where in the App.xaml of your start-up project I would link the Resource dictionary.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/myResourceLibrary;component/myResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
That way, you can just move the DLL around to whichever solution you want to use it in.

WPF - using styles/resources from another assembly

I'm new to WPF and struggling to use styles that live in a separate assembly. This is what I'm doing:-
I have a class library project with a \Themes folder containing a "generic.xaml" that merges a number of xaml files from a subfolder within \Themes:-
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Metro\CoreStyles.xaml" />
... etc ...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
My solution also has a WPF application project, and in here the App.xaml merges in the resources from my library project like so:-
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyThemeLibrary;component/Themes/generic.xaml"/>
... etc...
Standard stuff so far.
Finally, I have a third project - a WPF user control library. These controls use these common styles, typically with "Style={StaticResource SomeStyle}". I can run the app and it all looks fine, but the problem is I don't get design-time support when writing the user controls - the design surface is basically empty.
Another SO article suggested adding an App.xaml to the user control library project, and merging in the resources as above. This works and I get my design-time support, however I get an error when trying to build the solution:
Library project file cannot specify ApplicationDefinition element.
I have tried changing the App.xaml build action from "ApplicationDefinition" to "Page", as has been suggested elsewhere. This gets the build working but I lose the design-time support as the user controls can no longer see the styles.
Is there a way around this problem, or failing this, an alternative way of using styles from another assembly?
Thanks in advance
Andrew
The error message says it. You cannot use "pack://application..." syntax in a library project. You should do this in your wpf project.

How to properly organize XAML resources in Silverlight?

I'm having some issues with resource files in my modular application.
I have Infrastructure.DLL and some custom controls inside this DLL. Those controls using templates from themes/generic.xaml
Issue that I have - Blend doesn't recognize those resources. Visual studio does.
Ideally I'd like to have styles for my cusom controls inside generic.xaml and styles for other controls somewhere else in common library that I can reference from my modules.
I also need Expression Blend and VS to work properly.
How do I arrange solution to make it happen?
PS. Important! WPF is different but I'm interested in Silverlight solution
You just need to create design time resource for your generic.xaml in order to let Blend recoganize it. Take a look at this post.
In each of your modules, you create a ResourceDictionary like this.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
Source="/xxx.Silverlight.Controls;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Also, in your .csproj file, you need to add this. Please note that normally this piece of code is auto-generated by Blend, so if your ResourceDictionary is auto-generated, you don't need to do the following.
<Page Include="Design\DesignTimeResources.xaml" Condition="'$(DesignTime)'=='true' OR ('$(SolutionPath)'!='' AND Exists('$(SolutionPath)') AND '$(BuildingInsideVisualStudio)'!='true' AND '$(BuildingInsideExpressionBlend)'!='true')">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
Design is the folder I created for storing my DesignTimeResources.xaml. I pretty much have the same structure as yours. :)

Accessing base class Resources in a WPF Page class

I've got a custom WPF Application base class which has a set of resources specified in XAML in the Application.Resources property. I've changed the build action to Page from ApplicationDefinition.
Now I have another project, and I changed the App class to inherit from my custom application base above. However, I can't find how to access the resources which were specified in the base class's XAML file.
How can I load and access those resources, merging it with my derived Application classes Resources?
One thing you might be able to do is to use a merged dictionary. Its not exactly "inherited" but it works. I would separate out your resources into a shared xaml dictionary file, and then reference it from both your base Application, as well as your inheriting.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictonary Source="pack://application:,,,/ASSEMBLY;component/PATHTOSHAREDDICTIONARY"/>
</ResourceDictionary.MergedDictionaries>
<!-- More Resources can go here -->
</ResourceDictionary>
</Application.Resources>
I'm not sure how this is going to play with your Application, but it might be worth a shot. Good luck!
Note that ASSEMBLY and PATHTORESOURCEDICTIONARY will need to be replaced in your pack syntax.

Resources