Advice about sharing resources for Silverlight - silverlight

My company is slowly moving over to silverlight (from strictly asp.net apps) for our business enterprise. We have several large scale, web based applications, and different teams of developers work on the different products. Even though the products, and therefore the projects/solutions are separate, we do need to have some things in common. While data structures are definitely one of those things, my question today is about UI resources, such as common color themes, logos, styles, custom controls,localization, etc. I want to make sure that if make a change in one place, that the change will propagate to all our applications as seamlessly as possible.
Obviously (to me) App.xaml is the place to put most of these resources, however that still only covers one project, unless we make sure to import the same App.xaml into every project in every solution, and then provide a way to update that file (such as a link to it) when it changes. This sounds a little messy.
I'm wondering if anyone else has had to tackle this problem, and if you could share your techniques or ideas? Can any of these be stored in a database? In the cloud? Can it be easily stored in a *.dll and added to each project? How did you approach it?

The only thing you need to do is to put all your resources in one particular assembly and reference that assembly from your resource dictionary in app.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AltinetSilver;component/AltiStyles.xaml" />
<ResourceDictionary Source="Assets/AltiStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The first ResourceDictionary is from Assembly altinetSilver and it takes AltiStyles.xaml. The second one is the regular one. So i think that should cover it.

Related

XAML Intellisense doesn't work for Referenced Assembly Resources

I'm trying to create a project dll file that holds core styles, resources, controls, etc. This will then be referenced into various other projects to use as a graphic base to unify the appearance.
Anyway, I have the graphics project set up and I can use it in other projects and it all seems to display correctly. However, XAML intellisense for my static resources doesn't seem to be working.
Here is my resource dictionary reference:
<ResourceDictionary Source="pack://application:,,,/BIT.GraphicElements;component/BITCoreStyles.xaml" />
As you can see I'm using pack notation to reference it inside it's assembly. I can style elements like I would expect (StButtonAction is in the above dictionary):
Style="{StaticResource StButtonAction}"
However, I have to type it in manually. Intellisense doesn't give it as an option but if I type it manually is applies it successfully. It also works if I add the project to the solution and reference it there, however this is intended to be used by those that don't necessarily have access to the graphics project so that's not a good solution in the long run...
What am I missing? Is there a way to make Intellisense work for these?
Maybe this'll help future searchers even if it doesn't fix your specific problem.
When you have a solution involves external dll then you can occasionally find resources just don't get loaded at design time. At all. Even though you merge in app.xaml the things don't turn up until you run.
It looks like some sort of subtle bug to me.
The way I work round this is to use functionality originally intended for Blend. We are now using the blend designer in visual studio.
In solution explorer, add a resource dictionary to Properties. Yes. Properties. Create it first in your project and drag it up there. This must be called DesignTimeResources. This can then merge any resource dictionaries you will want to use just for design time or when you have an issue makes you think resource dictionaries aren't getting loaded for design time.
Mine is in army editor but uses resources from a referenced dll, UILIb. It looks like:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ArmyEditor">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/UILib;component/Resources/UILibResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
This is a resource dictionary in a bit of an odd place but nothing particularly weird so far.
Next is the bit that many developers will never have done - editing your csproj.
Right click your project and choose unload.
Right click it again and edit it.
In there you will have entries for all the stuff makes up your project. And of course breaking this would be bad so maybe you want to back up first.
If you don't use blend then I think the important thing here is to add a node which says ContainsDesignTimeResources True, but here's mine:
<Page Include="Properties\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>
Save your edits.
Reload your project.
When the designer is open, you should find resources from it are loaded. Maybe this will help intellisense find them.
I mentioned this earlier but.. In my experience, such intellisense on resources is often unreliable.
This definitely solved a similar issue I have had in this solution. It is also useful when you want to temporarily overlay resource dictionaries for localisation/branding testing.

Theme in MergedDictionary in Silverlight not working design time

Ok, this is driving me crazy now. I have a Silverlight 5 project. Not long ago we decided to theme our project, just to make it pop more. I found a theming implementation and went ahead.
First i used the .Theming namespace from the Silverlight Toolkit. I used the explicitly build theme.dll's. There was a shortcoming with this though, that i didnt have the ability to customize the theme. So i decided to just use the theme.xaml instead, and implement it by using <MergedDictionaries>.
The problem with this approach though, is that i lost the ability to see the theme in design time. In runtime it works fine. But that's just not good enough, when i wan't to customize the theme.
I implemented the theme by using merged dictionaries in App.Xaml like so
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/eCP;component/Themes/WhistlerBlue.xaml"/>
</ResourceDictionary.MergedDictionaries>
<vm:ViewModelLocator x:Key="ViewModelLocator"/>
</ResourceDictionary>
</Application.Resources>
If i put the same blok in my MainPage, the theme instantly turns on in design time there. But it shouldnt be necessary to do it on every Silverlight page?
So in short: If i implement the theme in with MergedDictionaries in App.xaml it does not work in design time. If i do it on a specific page, it does work.
Funny thing though, if i open my project in Expression Blend, it works fine in design time.
My first notion is, that something is messing with my visual studio 2010 SP1. Maybe something in a hidden project file or something, but i don't know.
Anyone able to help?

WPF Centralize xaml/image Resources in Multi-Tier/Project Application Solution

My situation is this.
I have multiple projects under a WPF solution which make up a multi-tier application I am developing. Since separate projects will sometimes need to access the same image or xaml resource I'd like to centralize "Public" resources to one project that can be referenced by any other projects requiring these "Public" resources. For example, I have a BMP image that I use in various controls and windows in separate projects that serves as a banner/logo. It seems like I should be able to add this image as a resource to the public resources project and reference it from my other projects instead of adding the image separately to every project that needs it. If this is possible, what would it look like and how should I go about doing it? If my idea just sucks I'm open to suggestions, but the project is going to be quite large so I don't want to be adding resources all over the place.
Thanks!
P.S.
I have searched this topic quite a bit but there are so many garbage answers out there from people that don't know what they are doing. Given that I'm relatively new to WPF I'd rather get a direct answer to my problem.
Well after some tinkering and research I found a solution to my own question. It seems like bits and pieces of my answer were scattered all over the web so I'll try to explain the whole thing at once, in one place. To re-cap I basically wanted to centralize any resources used across projects within my solution. These are the steps I eventually followed to accomplish this.
1.
Create a User Control project in your solution (any project that can host Resource Dictionaries will do). I'll refer to this project as "the resource project".
2.
Add any resource files (images etc...) that you want to share between projects to the resource project. I try to organize files in sub-directories that make sense. You will want to set the build action to "Resource" so that it gets compiled into the output binary.
3.
Now add a resource dictionary to the resource project. In my case I wanted to reference several images so I made one called "ImageDictionary.xaml".
4.
Add references to the image files in the resource dictionary. I am referencing images here but its just a resource dictionary, you can put whatever in there. The string in the middle is just the relative path to the image file you are referring to.
<ImageSource x:Key="SomeImageKey">
Images/SomeImage.bmp
</ImageSource>
5.
Now go to a project that requires the resource dictionary you just made in step 4. It can be another user control or a window, whatever. Right-click on project references and add a reference to the resource project.
6.
Okay now the current project needs to reference the dictionary you made in step 4 that is defined in the resource project. I made a user control first so this is what my code would look like below... Note that I used merged dictionaries. I plan on using more later so I chose this way instead of a single dictionary.
"ResourceProject" below is the name of the project/assembly that you added the resource to.
"component" is a keyword that needs to be there, followed by the path to the dictionary xaml code file.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ResourceProjectAssembly;component/Resources/ImageDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
As you can see, referencing an external resource dictionary requires something called a "Pack URI". I found a short hand way of doing it. The long way is quite a bit uglier and as far as I know, there is no advantage to it. But here is what the long way looks like.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/ResourceProjectAssembly;component/Resources/ImageDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
7.
Now that your current project has a reference to the resource dictionary in the resource project, you can use anything from that dictionary. I went ahead and put an image in my user control. Below is the code. Its just like referencing a dictionary locally.
<Image Source="{StaticResource SomeImageKey}" />
8.
Important Note!
This caused me a headache for a while before I found it. Make sure that the startup project in your solution has a reference to the resource project EVEN IF THE STARTUP PROJECT DOES NOT USE THE RESOURCE PROJECT. (I.e. right-click references, add reference etc...)
The resources will not get compiled into the output unless you do this. This part was tricky because the designer was even showing my images and I had no xaml errors but at runtime it would throw set property and cannot find file exceptions. This went away when I referenced my resource project from my startup project.
Hopefully this helps somebody.
Below are some links to a few places (including stackoverflow) that gave me what I needed to put all the pieces together.
http://blogs.msdn.com/b/wpfsldesigner/archive/2010/06/03/creating-and-consuming-resource-dictionaries-in-wpf-and-silverlight.aspx
Load WPF styles or other Static Resources from an external file or assembly
ResourceDictionary in a separate assembly

How can I discover WPF resources defined in another assembly?

I'm writing some extension modules for a WPF Composite application supplied by another vendor. The application is themed, and gives users the option to select from a number of themes which will change the appearance of the entire applications, including any custom modules that register themselves with the theme manager appropriately.
I really want my custom extensions to look like an integrated component, so I'm trying to use only styles defined as resources within the main application. As I'm still learning the nuances of XAML, I'm styling more by trial and error.
I'm wondering if there's a way of 'discovering' what styles are available in a different assembly. Here is an example of what I'm currently doing.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<common:DesignTimeResourceDictionary Source="/Vendor.Desktop.WPFCommon;component/themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Border
Background="{DynamicResource LightGradientBackgroundBrush}"
Margin="0"
>
The LightGradientBackgroundBrush is defined in the vendors assemblies. By including the above ResourceDictionary, the style is present during design time, and the brush isn't underlined in the XAML editor.
Can I find what other styles are defined? I'm only aware of that style because it was mentioned in passing in a sample provided by the vendor.
Edit:
I'm aware of a BAML add-in for reflector, but it doesn't work with reflector 7 unless it has been recompiled/patched. Someone has already done that here though.
I was hoping there was a better solution though. Intellisense for styles would be great.
There used to be a Reflector add-in for viewing BAML resources that worked well for that. But I haven't used Reflector in a while since Redgate crashed the party. It may not work with the current version.
You know where your resource dictionary is so you should be able to load it up in code and enumerate over the available resources. This will at least give you an idea of what's available.
See this link: http://blogs.claritycon.com/leeroth/2009/05/20/load-xaml-resource-dictionaries-at-runtime/
Enumerate over the Keys property and use the item property to access the resources. You can get as detailed as you want, but at the very least you should be able to spit out the resource names.

Silverlight: Multiple project sharing the same style files

I have multiple silverlight project that I would like to use the same styles, colour scheme, and some templated objects.
How do I accomplish this?
One way to do this would be to create a new silverlight class library which would be your shared theme/style assembly which would be referenced by the other silverlight projects. This assembly would have one or more Resource Dictionary XAML files in it which could define all of your styles, brushes and templates. You could even set up some cascading style hierarchies using the BasedOn attribute of the Style class.
You could then use MergedDictionaries to merge these styles into your application either at the App.xaml-level or on a page-level basis.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SharedThemeAssembly;component/MyStyles.xaml"/>
...other ResourceDictionaries to merge in...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
You would then reference the shared styles / brushes as you normally would any other StaticResource.
There are two options, first as Dan indicates you could create a library that is shared by the other projects. If the clients access several of your projects and your projects use application library caching then you reduce the total download size.
The other approach is to create a Resource dictionary in one project, then add the same file to the other projects. Note in the Add Existing Item dialog the add button has a small drop down image, drop it down and then select "Add as Link".
This leaves the dicitionary as a simple Xaml file. One advantage I can see for this is to actually leave the dictionary file out of the Xap and just place it in the clientBin folder (or whatever the folder that the Xap is placed in). This approach allows all the Xaps to share the single dictionary (in the same way the first approach does) but allows the Xaml to be tweaked without messy rebuilds.

Resources