I am trying to load a Silverlight project to read every XAML file by creating an instance using reflection, Activator.CreateInstance, of every XAML class for reading its controls.
C# Code:
string strPath = "SilverlightUI.dll";
StreamResourceInfo sri = Application.GetResourceStream(new Uri(strPath, UriKind.RelativeOrAbsolute));
AssemblyPart assemblyPart = new AssemblyPart();
Assembly assembly = assemblyPart.Load(sri.Stream);
Type[] typeArray = assembly.GetExportedTypes();
foreach (Type type in typeArray)
{
object ctl = (object)Activator.CreateInstance(type);
// Following exception is occurring while creating an instance using above line of code
// Exception "Cannot find a Resource with the Name/Key ComboBoxStyle"
}
Perhaps, reflection is not able to recognize Silverlight style ComboBoxStyle. How can i possibly create an instance to read every control in the XAML file dynamically?
I have managed to find the required solution to my problem after struggling with the Google.
Copy all the Style Resources from Silverlight project (intended to load).
Paste them in the App.xaml of the Master/Caller Silverlight project or application, which is using the reflection code to load the Silverlight Controls information
Following these steps will eliminate the XAML Parse Exception of missing Style.
Cannot find a Resource with the Name/Key ComboBoxStyle
Reference: XAML Parser cannot find resource within dynamically loaded XAP when creating form instance
I was able to load custom controls using the XamlReader class.
I am using plain string that contains the XAML of the control not like your reflection idea.
//string xaml = "<...>";
var content = XamlReader.Load(xaml) as FrameworkElement;
this.scrollViewer.Content = content;
The type XamlReader is in System.Windows.Markup.
If it is possible in your case you can try to get XAML resources from your assembly and read them to string. Then use the provided code. After you have the content variable you can do anything using the Silverlight API to the control.
Hope this will help you.
Related
In Resources.resx, when accessing a resource in C# visual studio, you do it by : "Properties.Resources." and then a list of resources is avaulable for selection.
I am trying to access resources without knowing the resource name in advanced, its name is revealed on run time only from a content of some string.
Is there any direct way to access the Resources.resx resources names or it can only be done by collecting all resources to a dictionary or some thing like that?
Yes, you can load the resource string manually using code similar to the below:
Assembly resourceAssembly = Assembly.Load("<AppName>.Resources");
ResourceManager resourceManager = new ResourceManager("<AppName>.Resources.<ResourceName>", resourceAssembly);
string resource = resourceManager.GetString("<ResourceName>", culture));
Just stumbled on an error that I can't seem to get rid of. I wanted to share it and check if that was just me or if anyone knew a workaround.
Context:
I have a scenario where I create a base class for user controls (abstract and inheriting from UserControl). While that base class has no XAML itself, I wish to load a resource dictionary containing styles that will be used by all child classes. Therefore I have to load this resource dictionary and load it in the merged resource dictionaries from my class C# code.
To reproduce the problem :
Create a new Silverlight 5 application with default settings (tested on VS2013 SP4)
Create a new resource dictionary at the root of the project. The name of the file is unimportant
Get to the MainPage code behind, and add these lines at the end of the constructor:
ResourceDictionary dic = new ResourceDictionary();
Uri source = new Uri("Dictionary1.xaml", UriKind.Relative);
dic.Source = source;
Run the solution. The project should crash at the last line of that snippet above, throwing an instance of the actual System.Exception class, with the message "Error HRESULT E_FAIL has been returned from a call to a COM component." Stack trace and trace output are unhelpful.
I've tried different things like waiting for the Loaded event, different kinds of Uris, but couldn't find any working variant.
So there you go. I'd be happy if anyone has an explanation, or has an idea about a different way to add a merged resource dictionary from C#.
Thanks
I'm trying to load a ResourceDictionary object into code so that I can check if it contains a certain value before trying to bind to it, but for some reason it can't find the resource. It might be something basic, ie having the wrong build action or URI but can someone point me in the right direction?
The .cs file and the Images.xaml resource dictionary are both in the same folder and namespace
This is the code that is failing
ResourceDictionary resourceDictionary = new ResourceDictionary();
resourceDictionary.Source = new Uri("Images.xaml", UriKind.Relative);
Any idea what I'm doing wrong? getting error message
{"Cannot locate resource 'images.xaml'."}
The XAML parser probably adds an application authority when converting URIs, in code you may need to add that yourself. Build action should just be the default for ResourceDictionaries, whatever that may be.
I have been trying to load a resource dictionary XAML file in my view model. I am able to instantiate it, and calls to it do not result in an immediate error, but after control returns to the UI, there is an error popup "Error HRESULT E_FAIL has been returned from a call to COM component".
I am doing the following:
ResourceDictionary file is ViewModelsResources.xaml located in MyApp/ViewModels where MyApp is the root folder of my Silverlight application
ViewModelsResources.xaml is marked Build Action: Content, Copy to Output Directory: Copy always, Custom Tool: MSBuild:Compile
The ResourceDictionary object is instantiated with (and this code is in a class in the same folder as the resource dictionary file)
ResourceDictionary VMResources = new ResourceDictionary()
{
Source = new Uri("/ViewModels/ViewModelsResources.xaml", UriKind.Relative)
};
The object is then referenced through index based on x:Key values: Template1 = VMResources["myTemplate"] as ControlTemplate; (same class as code sample above)
Debugging shows that VMResources and Template1 are being assigned good values. I don't know why this would be throwing errors about COM components, but I have isolated it to when this ResourceDictionary is referenced. If I take out the lines referencing VMResources[x] there is no error. Any help would be much appreciated.
Turns out this does work as I described, but you can't have events specified in the templates found in the resource dictionary. I should have realized that was going to cause problems, COM was throwing me off though. To get around the need for event handlers, I am using Behaviors. There's tons of reading out there on Behaviors. I started here and here.
note: If anyone believes I should delete this question since it actually works as proposed, just comment as so. I figure leaving this might help someone trying to do the same thing as me though.
I have a folder in my project, Templates, full of (compiled) XAML ResourceDictionaries.
In a UserControl, I want to load all the templates into the ResourceDictionary. I would use code like the following:
public MyView()
{
InitializeComponent();
foreach (var resourceUri in new GetResourceUrisFromTemplatesFolder())
Resources.MergedDictionaries.Add(
new ResourceDictionary
{ Source = new Uri(resourceUri, UriKind.Relative) });
}
What I need to write is the GetResourceUrisFromTemplatesFolder method. I need it to discover all the resources from that folder.
The URIs could take a form like /MyAssembly;component/MyNS/Templates/Template12345.xaml or ../../Templates/Template12345.xaml
Is this possible?
Do I have to manually convert the names from the assembly's compiled resources (MyAssembly.g.resources)?
BTW, one can also manually load a ResourceDictionary as it seems:
ResourceDictionary dict = new ResourceDictionary();
System.Windows.Application.LoadComponent(dict,
new System.Uri("/SomeAssembly;component/SomeResourceDictionary.xaml",
System.UriKind.Relative));
After that, can talk to that dict object using foreach on the Keys property it has etc
At http://msdn.microsoft.com/en-us/library/ms596995(v=vs.95).aspx says
The XAML file that is loaded can be either an application definition file (App.xaml, for example) >or a page file (MainPage.xaml, for example). The XAML file can be in one of the following locations:
Included in the application package.
Embedded in the application assembly.
Embedded within a library assembly at the site of origin.
Do I have to manually convert the names from the assembly's compiled resources (MyAssembly.g.resources)?
That might be the case and i myself would approach it that way, however the question about how to do just that has been answered already so it should be not that much of an issue. Make sure that the dictionaries' compile action matches, and you probably want to prefix the names with a pack uri.