WPF ResourceDictionary Loaded at Runtime Not Loading Referenced Assemblies - wpf

I've created a WPF application that contains some control templates which we can call 'default templates' and these templates are compiled into the application. This application also loads an external XAML file at runtime with additional control templates which can call 'custom templates'.
Everything works fine until I add a Callout control from the Expression Blend SDK to the 'custom' templates XAML that get loaded at runtime and then try to use that template. I get the following exception:
Cannot create unknown type '{http://schemas.microsoft.com/expression/2010/drawing}Callout'.
I noticed that if I put that Callout control in my 'default templates' file (the one that is compiled) and first use that default template, the then load and use the 'custom templates' it will work.
It seems to me that the referenced expression sdk assembly is not being loaded when I add my 'custom templates' to my MergedDictionaries. Any ideas here?
This is the xmlns declaration at the top of the XAML file:
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing
And this is the sub where I am adding the resource dictionary at runtime:
Private Sub LoadResourceFileButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Try
Dim path As String = "\ResourceFiles\CustomMapSymbols.xaml"
Dim resDict As New ResourceDictionary
resDict.Source = New Uri(path, UriKind.Relative)
Application.Current.Resources.BeginInit()
Application.Current.Resources.MergedDictionaries.Add(resDict)
Application.Current.Resources.EndInit()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub

I have similar symptoms in my situation where I get the following error:
Cannot create unknown type
'{htp://schemas.microsoft.com/expression/2010/drawing}Callout'.
However it works fine in a user control that is compiled in the application. This made me think that the ResourceDictionary implementation maybe doesn't handle the 'pretty' namespaces (htp://...) the same was as in the app.
So I tried referencing the explicit clr namespace directly in the declaration and it now works. I obviously had to change references in the rest of the xaml to ef:Callout. Easily done with auto replace. I didn't want to replace ed: with it in case I break Expression Blend that might be relying on it.
Old namespace declaration in the external resource dictionary:
xmlns:ed="htp://schemas.microsoft.com/expression/2010/drawing"
Sorry: I had to replace the http to htp to to post this answer.
New namespace declaration in the external resource dictionary:
xmlns:ef="clr-namespace:Microsoft.Expression.Controls;assembly=Microsoft.Expression.Drawing"
I found where the exact namespace was of the Callout class by using the Object Browser.

Related

Where do XAML files that build as "Page" go?

I've added a XAML file to a Windows Phone 8 project. Its build action is "Page". I want to load the XAML as a text string (to feed into XamlReader.Load()). How can I accomplish this?
It's not available as a separate file in the XAP package; it's probably somewhere in the DLL.
When set to Page, the compiler will compile the XAML into BAML and add the BAML file as a resource to the assembly.
If you wish to get the original XAML back out from the BAML resource at runtime, then you will need to deserialize the BAML, and then serialize your object to XAML.
You can have a look at the Baml2006Reader, or a better option would be to use Application.LoadComponent which is what the InitializeComponent method uses internally. InitializeComponent is called by the partially generated class for your XAML code behind.
var uri = new Uri("/MyAppName;component/MyXaml.xaml", //Note extension: XAML, not BAML
UriKind.Relative);
Page rootObject = new Page(); //Assuming XAML root element is Page - it could be anything
Application.LoadComponent(rootObject, uri);
(assuming the root element of your XAML file is a Page).
You can then serialize the Page to a XAML string using the XamlWriter:
string xaml = XamlWriter.Save(rootObject);
Note that this is the XamlWriter in the System.Windows.Markup namespace, not System.Xaml. If your XAML has WPF types, then you should use this XamlWriter to avoid errors.

Cannot load resource dictionary with converter

Everything happens within the same VS project. I have a resource dictionary file living on it's own. When I try to load it programmatically I get the error
"Cannot create unknown type '{clr-namespace:MyAssembly.Helpers}IsNullConverter".
Here is how I load it :
StreamResourceInfo stream = Application.GetResourceStream(new Uri(#"MyAssembly;component/Resources/Resources.xaml", UriKind.Relative));
this.dynamicResources = XamlReader.Load(stream.Stream) as ResourceDictionary;
And here is the resource dictionary :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:MyAssembly.Helpers">
<helpers:IsNullConverter x:Key="IsNullConverter" />
Styles go here...
Note that it is tied to a code-behind file, but there is nothing in it. The Build-Action of the resource file is set to "Resource". This is driving me crazy since this morning and still no clue what the heck is going on...
Help.
Thank you.
Halelujah I fugured it out. All I had to do is load the resource dictionary directly
Uri uri = new Uri(#MyAssembly;component/Resources/Resources.xaml", UriKind.Relative);
this.dynamicResources.Source = uri;
And make sure Build Action of resource dictionary file is set to "Page"
\m/
Is the assembly referenced by your project? If not try adding a reference - if you don't want a dependency you could try loading the assembly:
http://www.dreamincode.net/forums/topic/78974-using-reflection-to-load-unreferenced-assemblies-at-runtime/
Alternatively you could add a x:Class definition to the resourcedictionary, and instantiate the class from the assembly instead of loading the xaml, and remember to call the generated InitializeComponent() from the constructor, the it will load.
Is it possible to set code behind a resource dictionary in WPF for event handling?
Your example would work fine if the ResourceDictionary and converter was in the same assembly as where you load from, as far as I can see :)

Converting WPF application to UserControl for use in WinForms application via ElementHost

I'm trying to convert this WPF application to WPF UserControl so I could use it in WinForms application via ElementHost. I'm new to WPF and have never even touched it prior to this attempt so I might be going about it completely the wrong way.
I got the UserControl project to compile, however, my StaticResources get underlined in VS with message "The resource 'x' could not be resolved". I've tried moving the xamls with the needed x:Key elements up one level (the same level as the UserControl Dijagram.xaml), but it still cannot resolve them.
In the WinForms app, when trying to add the UserControl through designer by selecting hosted content in ElementHost tasks I get the following error:
An error occured trying to create an object of type
'DijagramLC.Dijagram'. Make sure the type has a default constructor.
(even though default constructor exists).
However, if I add it in codebehind, like this:
wpfUserControl = new Dijagram();
elementHost1.Child = wpfUserControl;
Controls.Add(elementHost1);
the code compiles but throws this runtime error: "System.Windows.Markup.XamlParseException: 'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '20' and line position '4'. ---> System.Exception: Cannot find resource named 'MyToolbar'. Resource names are case sensitive."
I've tried with and without App.xaml and adding ResourceDictionary elements for problematic xamls, but basically, I have no idea what I'm doing :)
I've uploaded the code to my SkyDrive and would really appreciate it if someone could take a look and tell me what I'm doing wrong:
https://skydrive.live.com/redir.aspx?cid=21be1f8e850e85cc&resid=21BE1F8E850E85CC!353
I hate jumping in blindly to new techonoly like this, but I have had no choice this time, and need to know if my requirement is even achievable this way.
You are probably getting the error because you use resources from a resource dictionary which is not loaded. Loading a resource dictionary in the hosting application will probably solve the issue:
// When hosting a WPF usercontrol inside an element host,
// application resources are not loaded, so we need to load them manually.
var resources = new ResourceDictionary
{
Source = new Uri("/UNIT4.MKB.GUI.XAML.Dashboard.Resources;component/resources.xaml", UriKind.Relative)
};
// Check for null reference
if (Application.Current != null)
{
//Merge the loaded ResourceDictornairy with the dummy application Resources.
Application.Current.Resources.MergedDictionaries.Add(resources);
}
The problem is, you need THE default constructor like this:
public CreatedPollsUC()
{
InitializeComponent();
}
If you have any other code in the constructor, the error occures:
public CreatedPollsUC()
{
InitializeComponent();
// ... more code
}
So if you want to use further code in the constructor, you need to apply the control first to the element host. Then you can edit the constructor.

Silverlight Custom Control in F# DefaultStyleKey

Wondering how to accomplish setting the Style xaml with the code in F#. The code is simple enough:
this.DefaultStyleKey <- typeof<MyControl>
In a C# project the build options allow you to mark the XAML as a resource custom build command of: MSBuild:Compile
I don't see it in the properties panel, so I tried to add it by hand to the project file myself...
Any ideas? The application loads - the custom control has no output (but the code executes).
Thanks
UPDATE:
I checked the manifests and the resource was included as expected between my project and the project I am porting... Looking for a next step.
UPDATE 2:
Well it may be included in the manifest OK - but it is not being "compiled" as the C# version of the project throws an error in the build process when I malform the XML while the F# version allows the malformed XML to be brought into the application.
UPDATE 3:
Loading the XAML is fine now (i guess) however I am having some issues with the properties of the control:
static member ItemsProperty : DependencyProperty =
DependencyProperty.Register(
"Items",
typeof<MyMenuItemCollection>,
typeof<MyMenu>,
null);
member this.Items
with get () : MyMenuItemCollection = this.GetValue(MyMenu.ItemsProperty) :?> MyMenuItemCollection
and set (value: MyMenuItemCollection) = this.SetValue(MyMenu.ItemsProperty, value);
The problem occurs on access:
for menuItem in this.Items do
let contentElement: FrameworkElement = menuItem.Content
where I get a null pointer exception on this.Items; however I have it initialized in the constructor:
do
this.Items <- new CoolMenuItemCollection()
The C# style of compilation of XAML files is not supported by the F# tools for Visual Studio, so there is no way to get the same behavior as in C#. I think you have two options:
Create a C# project with XAML files and reference F# library which implements the core functionality (or reference C# library from F# and load user interface from the C# library in your F# application)
Use XamlReader object (see MSDN) and load the XAML file (embedded in resources in the simple way) programmatically. You won't get any of the C#-compiler generated features (e.g. named properties for all objects with x:Name), but otherwise, it should work in the usual way.

navigation framework in silverlight 3 skipping constructor when usercontrol is of a derived type

I am using the NavigationFramework in Silverlight 3, and am running into issues where the constructor of the UserControl in the xaml I am loading is not being called, and I believe this is because the UserControl in the xaml I am calling is actually derived from another user control.
I have stepped through the debugger with specific break points and the constructor is being ignored completey.
I have MyWindowBlue which is of type uctrlBaseMyWindow.
The constructor for uctrlBaseMyWindow is being called when the xaml is 'navigated to' but the constructor for MyWindowBlue is being ignored.
This is not the case if I add the user control via markup directly.
Anyone else have this issue?
The code I am using to navigate to the MyWindowBlue is
this.MyContentFrame.Navigate(new Uri("/Controls/uctrlMyWindowBlue.xaml", UriKind.Relative));
Has anyone run into this or could offer any help?
Thanks
Found the error in my code.
This was due to an error in my XAML. I had moved the user control to a different folder, and so the c# code behind had a type of the same name in one location in the namespace, but the XAML markup had the type in a different location (the original folder), and so the partial class with the constructor was not linked to the type I was actually instantiating.
I fixed the type reference to point to the proper location in the namespace and now the partial class code behind is linked back up.

Resources