Impossible to embed WPFToolkit into my executable? - wpf

I made a post about this a while back and got no solutions that worked.
No one said it wasn't possible but some people suggested that the error was coming from something else.
So I created a new solution, simple, just added a toolkit control which calls the DLL via the XAML (namespace import) - which I think is the problem.
I added some code to load the DLL's which I have embedded as resources.
my project can be downloaded from here:
https://onedrive.live.com/redir?resid=B293BA834310C42A%21108
for those who don't have time, here's the code:
MainWindow.xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" x:Class="WpfAppTest1.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<chartingToolkit:ScatterSeries HorizontalAlignment="Left" Margin="63,85,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
MainWindow.xaml.cs
namespace WpfAppTest1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
and my App.xaml.cs
namespace WpfAppTest1
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var execAssembly = Assembly.GetExecutingAssembly();
string resourceName = execAssembly.FullName.Split(',').First() + ".Resources." + new AssemblyName(args.Name).Name + ".dll";
Console.WriteLine(resourceName);
using (var stream = execAssembly.GetManifestResourceStream(resourceName))
{
byte[] assemblyData = new byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}
}
}
The 2 DLL's are:
system.windows.controls.datavisualization.toolkit.dll
WPFToolkit.dll
Both are added as Resources and build action is set to Embedded Resource.
The 2 references are copy local to False.
Looking at the EXE, both files are well built into it.
I added a console writeline to print out the path of the DLL being loaded...
But I still get an error. If I do set the copy local to true, it works.
I am really stuck there and have to use this toolkit and I need the DLL to be part of the EXE. If it's not possible then I'd like to read it from one of you pro's :)
thanks
Steve
edit: Is there no solution to achieve what I need? :(
edit: I still haven't found a solution as of today :/
edit: I wonder if this is even possible.

After quite a bit of effort I seem to have this working.
As your resource for system.windows.controls.datavisualization.toolkit is all in lower case, ensure all of the XAML references to it are also, e.g.:
xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=system.windows.controls.datavisualization.toolkit"
This ensures Assembly.GetManifestResourceStream is able to find the resource without any casing issues.
Then change your assembly resolve method to be the following:
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var requestedAssemblyName = new AssemblyName(args.Name).Name;
const string resourcesExtension = ".resources";
if (requestedAssemblyName.EndsWith(resourcesExtension, StringComparison.Ordinal))
{
requestedAssemblyName = requestedAssemblyName.Remove(requestedAssemblyName.Length - resourcesExtension.Length);
}
var resourceName = "WpfAppTest1.Resources." + requestedAssemblyName + ".dll";
var appAssembly = typeof(App).Assembly;
using (var stream = appAssembly.GetManifestResourceStream(resourceName))
{
// Check the resource was found
if (stream == null)
return null;
var assemblyData = new byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
var loadedAssembly = Assembly.Load(assemblyData);
return loadedAssembly;
}
}
The key point to note is the removal of the .resources extension which sometimes comes through when resolving assemblies
This is enough to get the assembly loading from the resources, however there will be no implicit styling applied to the charting controls (I am assuming this is to do with how WPF discovers its themes at runtime).
To work around this problem, I put the following in App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/system.windows.controls.datavisualization.toolkit;component/Themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
This merges the default chart styles which should then get implicitly applied.
To test it, I used the following content in MainWindow.xaml:
<chartingToolkit:Chart Title="Some Chart" Background="Blue">
<chartingToolkit:Chart.Series>
<chartingToolkit:ScatterSeries Title="Series 1" />
</chartingToolkit:Chart.Series>
</chartingToolkit:Chart>

Related

Is it possible to load an external hosted XAML file into a WPF project?

Is it possible to load an external hosted XAML file into a WPF project?
I am trying to pull in a ResourceDictionary from an external XAML file. I am doing this so I can style the application external from the application.
I am doing this because I want to see if this is possible because the application is going to be running on multiple computers and I don't want to have to reload upload or load a new XAML file everytime I need to make a simple change to a button color or text color.
Below are 2 options I have tried but I keep getting that the resource can not be an absolute URI. Any pointers on how to make my XAML file load from an external hosted source?
Try one
namespace FunWithXaml
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
EnsureApplicationResources();
InitializeComponent();
}
public static void EnsureApplicationResources()
{
if (Current == null)
{
// create the Application object
// new Application();
// merge in your application resources
Current.Resources.MergedDictionaries.Add(
LoadComponent(
new Uri("http://example.com/scripts/XAMLTest.xml", //This can be .xaml or .xml from my understanding if it does not have the x:Class declared in the file.
UriKind.RelativeOrAbsolute)) as ResourceDictionary);
}
else
{
MessageBox.Show("Welp that didn't work.");
}
}
}
Try Two. Similar to above but I try to do it with using the WebClient and XamlReader. Not sure if I am doing this part correctly though.
var Blob = new Uri("http://example.com/scripts/XAMLTest.xml");
var wc = new WebClient();
var sourceStream = wc.OpenRead(Blob);
StreamReader mysr = new StreamReader(sourceStream);
FrameworkElement rootObject = XamlReader.Load(mysr.BaseStream) as FrameworkElement;
Current.Resources.MergedDictionaries.Add(LoadComponent(rootObject)); //rootobject is giving me red lined error.
And Try Three. Similar to Try One but completely did away with the "If" and get an error stating I can't have an absolute URI.
public static void EnsureApplicationResources()
{
Current.Resources.MergedDictionaries.Add(
LoadComponent(
new Uri("http://example.com/scripts/XAMLTest.xml",
UriKind.RelativeOrAbsolute)) as ResourceDictionary);
}
EDIT
Try Four based on the suggestion below by #Leon Zhou. But I am getting an exception error:
"An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll
Additional information: ResourceDictionary LoadFrom operation failed with URI 'http://example.com/scripts/XAMLTest.xml' ".
public App()
{
AFunction();
InitializeComponent();
}
public void AFunction()
{
var foo = new Uri("http://example.com/scripts/XAMLTest.xml", UriKind.Absolute);
Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = foo });
}
This what's in my XML file I am trying to pull.
<ResourceDictionary>
<Style x:Key="HeaderStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green"/>
</Style>
</ResourceDictionary>
This is my App.xaml file
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="FunWithXaml.App"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--Trying to get dynamic XML/XAML resource to populate here-->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
How about:
Application.Current.Resources.MergedDictionaries.Add(
new ResourceDictionary { Source = uri }
);
var uri = new Uri("PathToMyXamlFile");
var stream = File.OpenRead(uri.ToString());
var resources = (ResourceDictionary)XamlReader.Load(stream);
I would get the Xaml as a String into a memory stream. And then give it to the XamlReader.Load.

Why can I not set a SolidColorBrush resource value from code?

I have a resource defined in my xaml :
<core:WidgetBase xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="....Silverlight.LiquidityConstraintsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:core="clr-namespace:...Silverlight;assembly=....Silverlight"
xmlns:local="clr-namespace:....Silverlight"
mc:Ignorable="d">
<core:WidgetBase.Resources>
<SolidColorBrush x:Key="..." />
</core:WidgetBase.Resources>
...
I am trying to set it from code :
void _administrationClient_GetByFilterModuleSettingCompleted(object sender, GetByFilterModuleSettingCompletedEventArgs e)
{
this.Resources["..."] = new SolidColorBrush(Colors.Red);
}
But I get the error :
The method or operation is not implemented.
stack trace :
at System.Windows.ResourceDictionary.set_Item(Object key, Object value)
at ....Silverlight.LiquidityConstraintsView._administrationClient_GetByFilterModuleSettingCompleted(Object sender, GetByFilterModuleSettingCompletedEventArgs e)
at ....Service.AdministrationServiceClient.OnGetByFilterModuleSettingCompleted(Object state)
It happens when I send off a request to a server to fetch me a colour, then when it returns I try and set that colour to the resource, it fails even if I try and set it as red at that point.
If it at all helps, the method in which I am setting this is an async callback method from WCF call to a server.
If you look at the setter for ResourceDictionary in Reflector (for Silverlight), you'll see it throws a NotImplementedException, so this will not work in Silverlight.
You could try removing the resource and re-adding it, but that's a shot in the dark.
"This indexer implementation specifically blocks a "set" usage. If you attempt to set a value using the indexer, an exception is thrown. You must remove and re-add to the ResourceDictionary in order to change a key-value pair."
http://msdn.microsoft.com/en-us/library/ms601221(v=vs.95).aspx
This operation will work as expected if you try it in a new WPF Application:
<Window.Resources>
<SolidColorBrush x:Key="Brush" Color="Aqua" />
</Window.Resources>
public MainWindow()
{
this.Resources["Brush"] = new SolidColorBrush(Colors.Green);
InitializeComponent();
}
Therefore, I suggest to you that your problem lies elsewhere.
UPDATE >>>
How about avoiding this problem altogether and simply using a public property in your MainWindow.xaml.cs?
In MainWindow.xaml.cs:
public SolidColorBrush Brush { get; set; }
Then anywhere in your application, you should be able to access this property like this:
((MainWindow)App.Current.MainWindow).Brush = new SolidColorBrush(Colors.Red);

Memory leak when using SharedResourceDictionary

if you worked on some larger wpf applications you might be familiar with this. Because ResourceDictionaries are always instantiated, everytime they are found in an XAML we might end up having one resource dictionary multiple times in memory. So the above mentioned solution seems like a very good alternative. In fact for our current project this trick did a lot ... Memory consumption from 800mb down to 44mb, which is a really huge impact. Unfortunately this solution comes at a cost, which i would like to show here, and hopefully find a way to avoid it while still use the SharedResourceDictionary.
I made a small example to visualize the problem with a shared resource dictionary.
Just create a simple WPF Application. Add one resource Xaml
Shared.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="myBrush" Color="Yellow"/>
</ResourceDictionary>
Now add a UserControl. The codebehind is just the default, so i just show the xaml
MyUserControl.xaml
<UserControl x:Class="Leak.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SharedResourceDictionary="clr-namespace:Articy.SharedResourceDictionary" Height="128" Width="128">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Leak;component/Shared.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Rectangle Fill="{StaticResource myBrush}"/>
</Grid>
</UserControl>
The Window code behind looks something like this
Window1.xaml.cs
// [ ... ]
public Window1()
{
InitializeComponent();
myTabs.ItemsSource = mItems;
}
private ObservableCollection<string> mItems = new ObservableCollection<string>();
private void OnAdd(object aSender, RoutedEventArgs aE)
{
mItems.Add("Test");
}
private void OnRemove(object aSender, RoutedEventArgs aE)
{
mItems.RemoveAt(mItems.Count - 1);
}
And the window xaml like this
Window1.xaml
<Window.Resources>
<DataTemplate x:Key="myTemplate" DataType="{x:Type System:String}">
<Leak:MyUserControl/>
</DataTemplate>
</Window.Resources>
<Grid>
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="Add" Click="OnAdd"/>
<Button Content="Remove" Click="OnRemove"/>
</StackPanel>
<TabControl x:Name="myTabs" ContentTemplate="{StaticResource myTemplate}">
</TabControl>
</DockPanel>
</Grid>
</Window>
I know the program is not perfect and propably could be made easier but while figuring out a way to show the problem this is what i came up with. Anyway:
Start this and you check the memory consumption, if you have a memory profiler this becomes much easier. Add (with showing it by clicking on the tab) and remove a page and you will see everything works fine. Nothing leaks.
Now in the UserControl.Resources section use the SharedResourceDictionary instead of the ResourceDictionary to include the Shared.xaml. You will see that the MyUserControl will be kept in memory after you removed a page, and the MyUserControl in it.
I figured this happens to everything that is instantiated via XAML like converters, user controls etc. Strangely this won't happen to Custom controls. My guess is, because nothing is really instantiated on custom controls, data templates and so on.
So first how we can avoid that? In our case using SharedResourceDictionary is a must, but the memory leaks makes it impossible to use it productively.
The Leak can be avoided using CustomControls instead of UserControls, which is not always practically. So why are UserControls strong referenced by a ResourceDictionary?
I wonder why nobody experienced this before, like i said in an older question, it seems like we use resource dictionaries and XAML absolutely wrong, otherwise i wonder why they are so inefficent.
I hope somebody can shed some light on this matter.
Thanks in advance
Nico
I'm running into the same issue of needing shared resource directories in a large-ish WPF project. Reading the source article and the comments, I incorporated a couple fixes to the SharedDirectory class as suggested in the comments, which seem to have removed the strong reference (stored in _sourceUri) and also make the designer work correctly. I tested your example and it works, both in the designer and MemProfiler successfully noting no held references. I'd love to know if anyone has improved it further, but this is what i'm going with for now:
public class SharedResourceDictionary : ResourceDictionary
{
/// <summary>
/// Internal cache of loaded dictionaries
/// </summary>
public static Dictionary<Uri, ResourceDictionary> _sharedDictionaries =
new Dictionary<Uri, ResourceDictionary>();
/// <summary>
/// Local member of the source uri
/// </summary>
private Uri _sourceUri;
/// <summary>
/// Gets or sets the uniform resource identifier (URI) to load resources from.
/// </summary>
public new Uri Source
{
get {
if (IsInDesignMode)
return base.Source;
return _sourceUri;
}
set
{
if (IsInDesignMode)
{
try
{
_sourceUri = new Uri(value.OriginalString);
}
catch
{
// do nothing?
}
return;
}
try
{
_sourceUri = new Uri(value.OriginalString);
}
catch
{
// do nothing?
}
if (!_sharedDictionaries.ContainsKey(value))
{
// If the dictionary is not yet loaded, load it by setting
// the source of the base class
base.Source = value;
// add it to the cache
_sharedDictionaries.Add(value, this);
}
else
{
// If the dictionary is already loaded, get it from the cache
MergedDictionaries.Add(_sharedDictionaries[value]);
}
}
}
private static bool IsInDesignMode
{
get
{
return (bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
typeof(DependencyObject)).Metadata.DefaultValue;
}
}
}
I am not quite sure if this will solve your issue. But I had similar issues with ResourceDictionary referencing controls and its to do with lazy hydration. Here is a post on it. And this code resolved my issues:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
WalkDictionary(this.Resources);
base.OnStartup(e);
}
private static void WalkDictionary(ResourceDictionary resources)
{
foreach (DictionaryEntry entry in resources)
{
}
foreach (ResourceDictionary rd in resources.MergedDictionaries)
WalkDictionary(rd);
}
}

How to add a Marker to ArcGIS map (Silverlight)

I am teaching my self arcGIS maps via the Silverlight API for work, and i was trying to do a simple, place marker symbol at XY example, but darn it if I can't get it to work! I am using the following sample page as a reference, but when i go to debug the thing, my marker always ends up dead center of the map, regardless of what the MapPoint's X and Y values:
http://blogs.esri.com/dev/blogs/silverlightwpf/archive/2010/12/14/adding-gps-location-to-the-map-in-the-arcgis-api-for-windows-phone.aspx
my xaml looks as follows:
<UserControl x:Class="CustomGeometry.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<esri:Map x:Name="mapWells" Loaded="mapWells_Loaded">
<esri:ArcGISTiledMapServiceLayer x:Name="BaseLayer" ID="Base Map" Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
</esri:Map>
</Grid>
</UserControl>
my back end code looks like the following:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
/// <summary>
/// creating Wells Layer
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void mapWells_Loaded(object sender, RoutedEventArgs e)
{
GraphicsLayer wellsLayer = mapWells.Layers["WellsLayer"] as GraphicsLayer;
if (wellsLayer == null)
{
wellsLayer = new GraphicsLayer()
{
ID = "wellsLayer"
};
mapWells.Layers.Add(wellsLayer);
Graphic marker = new Graphic();
marker.Symbol = new SimpleMarkerSymbol();
wellsLayer.Graphics.Add(marker);
}
// map point not being set correctly.
MapPoint location = new MapPoint(-122.466903686523, 48.7440490722656, mapWells.SpatialReference);
wellsLayer.Graphics[0].Geometry = location;
}
}
What am I doing wrong? I'm assuming it has to do with the spatialReference, but the maps spatial reference is null. Help!
Found the issue. While the walkthough example stated that the GeographicToWebMercator was optional, it clearly is not. When I replaced the line
wellsLayer.Graphics[0].Geometry = location;
with
wellsLayer.Graphics[0].Geometry = ESRI.ArcGIS.Client.Bing.Transform.GeographicToWebMercator(location);
the map marker moves to a location based upon my map point, because while the latitude and longitude might be correct to the given Spacial reference system, the bing maps system has to convert those values to something it knows how to display on the current projection.
Hope this helps others!

Silverlight Shared MergedDictionaries

I am using Silverlight 4 and trying to share some common styles (colors, brushes).
My take was to put them into a "Common.xaml" Resource Dictionary and then use it in all other Resource Dictionaries.
Referencing everything like so:
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SampleApp.App"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Assets/Styles/Common.xaml"/>
<ResourceDictionary Source="Assets/Styles/TextBoxStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The problem is, that I get an exception on InitializeComponent stating that the common styles cannot be found (Cannot find a Resource with the Name/Key....)
I have to explicitly Reference the "Common.xaml" in every Resource Dictionary where I use it.... And this basically result in multiple Instances of every color, brush, template and whatnot that resides in "Common.xaml".
Isn't there any way to share Resources so the only get instanziated once in Silverlight?
The problem is that silverlight appears to streamline loading of resource dictionaries such that multiple dictionaries can be loading in parallel. As a result when one dictionary has a dependency on another that dependency may not be ready in time.
Since ResourceDictionary doesn't have builtin means to describe inter-dependencies nor an event to indicate when it has loaded the only solution I've been able to come to is to manage the loading of the dictionaries myself.
Here is a function you can add to your App.xaml.cs file to "manually" load a resource dictionary:-
private void LoadResource(Uri uri)
{
var info = Application.GetResourceStream(uri);
string xaml;
using (var reader = new StreamReader(info.Stream))
{
xaml = reader.ReadToEnd();
}
ResourceDictionary result = XamlReader.Load(xaml) as ResourceDictionary;
if (result != null)
{
Resources.MergedDictionaries.Add(result);
}
}
Now in the Application_Startup before assigning RootVisual you would use code like:-
LoadResource(new Uri"Assets/Styles/Common.xaml", UriKind.Relative));
LoadResource(new Uri("Assets/Styles/TextBoxStyle.xaml", UriKind.Relative));
It isn't going to be as efficient as using the Source property but it will work. If you have many such dictionaries and only few "common" dictionaries that contain shared resources then you could use this technique to load only the "common" dictionaries then use:-
Resource.MergedDictionaries.Add(new ResourceDictionary() {Source = new Uri("Assets/Styles/TextBoxStyle.xaml", UriKind.Relative)});
For the other dictionaries that don't have interdependencies on each other.
I was able to tweak the solution proposed at http://www.wpftutorial.net/MergedDictionaryPerformance.html
to make it work with Silverlight and the VS designer (haven't tried Blend). I have a blog post on it here (http://softnotes.wordpress.com/2011/04/05/shared-resourcedictionary-for-silverlight/)
public class SharedResourceDictionary : ResourceDictionary
{
public static Dictionary<Uri, ResourceDictionary> _sharedDictionaries =
new Dictionary<Uri, ResourceDictionary>();
private Uri _sourceUri;
public new Uri Source
{
get { return _sourceUri; }
set
{
_sourceUri = value;
if (!_sharedDictionaries.ContainsKey(value))
{
Application.LoadComponent(this, value);
_sharedDictionaries.Add(value, this);
}
else
{
CopyInto(this, _sharedDictionaries[value]);
}
}
}
private static void CopyInto(ResourceDictionary copy, ResourceDictionary original)
{
foreach (var dictionary in original.MergedDictionaries)
{
var mergedCopy = new ResourceDictionary();
CopyInto(mergedCopy, dictionary);
copy.MergedDictionaries.Add(mergedCopy);
}
foreach (DictionaryEntry pair in original)
{
copy.Add(pair.Key, pair.Value);
}
}
}
XAML usage:
<ResourceDictionary.MergedDictionaries>
<ui:SharedResourceDictionary Source="/my_assembly_name;component/Resources/Shared.xaml"/>
</ResourceDictionary.MergedDictionaries>
If you get an error loading, ensure the Build Action is set to one of the following:
//In the dll, which is in the xap, marked as Build Action: Resource or Page
LoadResource(new Uri("SilverlightApplication48;component/GlobalAssets.xaml", UriKind.Relative));
//In the xap at the same level as the dll, (not in the dll) marked as Build Action: Content.
LoadResource(new Uri("Dictionary1.xaml", UriKind.Relative));
//In a separate library, marked as Build Action: Resource or Page.
LoadResource(new Uri("StylesLibrary;component/Dictionary2.xaml", UriKind.Relative));
Greg
Another interesting note on this thread is that SL only keeps ONE copy of a style if it is found in two different dictionaries. The last one wins. In other words, if you have two different styles both with the same key, the first one is discarded when the second one loads.

Resources