Namespace problem while loading XAML dynamically - c#

I have a WPF application that load a FlowDocument from a embedded resource, with the following code
object something = XamlReader.Load( stream );
The parser tell me he cannot find the "clr-namespace:ReportPrinter" at
<FlowDocument
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:ReportPrinter"
>
A quick search with google tell me i need to specify the assembly, but how i can do it?

You simply append the name of the assembly containing the specified class to the definition of the namespace. A good example of the correct string can be found at MSDN. There is also a description about the different possibilities to describe a certain assembly.

Related

Invalid ResourceDictionary clr-namespace

When I add a ResourceDictionary to a folder its clr-namespace is invalid.
Adding a class to the same folder
[
corrects the error
How can I resolve the clr-namespace without having to add a class to the folder?
Addendum
Note: Removing the dummy class invalidates the namespace again.
Thans Ali Bigdeli!
There are actually 2 errors:
Severity Code Description Project File Line Suppression State
Error IDE1100 Error reading content of source file 'C:\path\TS\ResourceDictionaries\RoundButtons.xaml' -- 'Could not find file 'C:\path\TS\ResourceDictionaries\RoundButtons.xaml'.'. TS-XamlProject C:\path\TS\ResourceDictionaries\RoundButtons.xaml 1 Active
Severity Code Description Project File Line Suppression State
Error XLS0419 Undefined CLR namespace. The 'clr-namespace' URI refers to a namespace 'TS.StyleDictionaries' that could not be found. TS Style1.xaml 4
You don't need an xmlns reference in a resource dictionary for it to work.
Let's start an explanation by considering what an xmlns is doing.
When you add an xmlns that is going to pull some compiled objects into memory so you can use them in your resource dictionary. It will also alias these. Usually. One of the default ones does not, but anything you add yourself will therefore need to.
Every resource dictionary has by default some of these added so you can use things like Style. What those default namespaces are referencing is fundamentals of the framework.
Hence
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Without that top default xmlns, you couldn't put a style or datatemplate in your resource dictionary. These are classes which are defined in the net framework.
The second illustrates aliasing and allows you to use the likes of x:Name and x:Type.
<Button x:Name="FooButton"
Say you wanted a string as a resource.
This is not in the default namespaces, so you need to add an xmlns to use string. It's a class.
https://learn.microsoft.com/en-us/dotnet/api/system.string?view=netcore-3.1
In .net old this was in mscorlib. In net core it's moved.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
>
<sys:String x:Key="Submit">Submit</sys:String>
So here, I'm telling it I need to load namespace System from System.Runtime.dll and I want to alias that as sys. In that is the string class which I hence reference in xaml as sys:String.
If I had a usercontrol in the root of wpfapp1 that would be
<local:UserControl1
Bearing in mind that a usercontrol has code behind and if you took a look in such a usercontrol code behind, you'd see the namespace wpfapp1.
The xaml in a resource dictionary or window knows nothing about your code. It works with compiled objects. Which is why if you add a converter and try and reference it immediately in a resource dictionary you will see an error. Because that converter hasn't been compiled yet so when the designer uses reflection on the exe or dll it's in, the converter is not there.
That's covered the background to xmlns, let's take a look at namespaces.
When you add a folder to a project structure, this is just a folder.
When you add some code like a class, there's a template which is used to create that stub you get. Create class1 and you get some usings, a namespace and a stub class. This is all built from a template.
You could edit these actually, these templates are "just" files on disk.
When it does this the stub creation process VS looks at your project and the folder you're creating a class in. If you create class1 in the root of project TS then you get a namespace TS. Drag that into some other folder and it's namespace stays as TS. There is no hard link between folder structure and namespace. Add .Banana to the namespace declaration in that class1 and you'd get a TS.Banana namespace once you compiled.
Within your compiled exe ( which the xaml will reflect to see what's in there ) a namespace only exists because there's some code compiled which has that namespace.
If you have some code with the namespace TS.StyleDictionaries then when it's compiled you will have that namespace in your exe or dll.
If you do not have any code with that namespace then when you compiled you will not have that namespace in there at all.
This is the cause of the different behaviour you're seeing when you add a "dummy" class and remove it.
Add it, you get the namespace.
Remove it, you have no code with that namespace and it's not in the compiled exe/dll.
A resource dictionary, by default, has no code behind. It's all about xaml and if you look in that there's nothing looks like a namespace. XAML is rather different from code and when you merge a resource dictionary in app.xaml you end up with entries in a sort of dictionary<string, object> which is application.current.resources. To reference these from your app all you need is the key. These are in memory.
This is significant (partly) because, if you recall, the point of an xmlns is to pull compiled code into memory.
I mention this to highlight how different xaml resources and c# objects are in usage.
This is also more a conceptual explanation and glosses over some details. The actual object in memory might only be instantiated when you first use it. That's way beyond beginner knowledge though.
Hopefully this is clear without completely beating the subject to death.
You need have at least one class in mentioned namespace.
ResourceDictionary can be with codebehind (xaml.cs) file.
How to add resourceDictionary with codebehind
When you add new item to project.. you need to choose Page or UserControl
Than you need change your xaml.cs file: specify your namespace and className which need inherit from ResourceDictionary (instead of Page or UserControl)
using System.Windows;
namespace TS.StyleDictionaries
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Theme : ResourceDictionary
{
public Theme()
{
InitializeComponent();
}
}
}
After that in xaml you need replace Page to ResourceDictionary, additionally specify x:Class attribute and than you can specify your local namespace xaml.
<ResourceDictionary x:Class="TS.StyleDictionaries.Theme"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TS.StyleDictionaries">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="\Themes\ButtonsStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
P.S.
You need specify namespace only when you need to use clr type from it.
For use resources from other ResourceDictionary you can use MergedDictionaries or put shared ResourceDictionary inside App.xaml

What does xmlns:dc mean in C# WPF?

What does xmlns:dc mean in C# WPF XAML code? Can't find anything on it. Is it directory context? Domain controller?
Sorry for missing context.
I know xmlns is just xaml name space, but i want to know what dc stands for, like what does it mean?
xmlns:dc="clr-namespace:SomethingHere;assembly=SomethingHere"
"dc" is an arbitrary prefix - it is used to reference the namespace as a short hand way, but can be anything you like.
Here's the explanation by the guy who thought it up:
http://www.xml.com/pub/a/1999/01/namespaces.html
dc would just be the namespace of a control you're trying to use, so if you wanted to use a control called ThisControl that was inside the assembly "clr-namespace:SomethingHere;assembly=SomethingHere" you would need to use dc:ThisControl in the xaml.
Working with Cytoscape I have found that xmlns:dc refers to XLM Namespace(xlmns) and the Dublin Core(dc) metadata standard:
https://www.dublincore.org/specifications/dublin-core/dcmi-terms/
When exporting xgmml from cytoscape, part of the xml refers to http://purl.org/dc/elements/1.1/ which redirects to the url above.
Example:
<graph id="78" label="TAPBPL" directed="1" cy:documentVersion="3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cy="http://www.cytoscape.org" xmlns="http://www.cs.rpi.edu/XGMML">

XAML (WPF) Namespace?

I have been trying to read up on XAML namespace and the use of xlmnr and it has been kind of fuzzy. Either it is too technical, or too simplistic.
My question is a little similar to a question asked here, but my question has more to do with the x part attached to it.
So:
Does the xmlns:x, mean a secondary namespace? i.e. the non-default one? Can I have more than one, and if so what order does the search for the right class go in? This of course assumes that xmlns is the default one.
What about the meaning of and difference of attaching x:name as opposed to name to a tag?
Edit:
Turns out, I think I completely misunderstood it. There is no search hiearchy like C# using statement, or java's import. The xmlns:<name> is more like a way to define a name that you can access a whole tree of classes. The x on the other hand is a conventional way to define XMAL related stuff, but is not a requirement.
Can anyone confirm?
The use of XML namespaces in XAML is necessary because of the underlying XML technology used.
xmlns:x indeed creates a second namespace named x. You can reference attributes, etc from it using x:....
If you had simply use name instead of x:name it would have referenced the default namespace.
You can have as much namespaces declared in your XAML as needed.
The standard x namespace exposes common XAML features - basically a mapping of various things that are implemented in code to give them meaning in the XAML context. In the case of x:Name (not x:name - case matters) the XAML compilation process creates a code-behind field based on the x:Name value. The non-x Name property is an attribute representing the Name property on the WPF FrameworkElement base class, which in most cases works the same way as setting the x:Name, and you can't assign both on the same element. See this question for more info.
To the first part of your question: you can change the x to whatever you want, but shouldn't to maintain consistency, and can also (and will in practice) add other xmlns: declarations, primarily to access additional feature implemented in code. For example, if you work in Blend you will often see a xmlns:d added which contains a bunch of designer specific properties. Any code that you need to reference, like data types, converters, etc. will generally use an xmlns: with clr-namespace and assembly specified to map to the .NET namespace in the code: i.e. xmlns:local="clr-namespace:WpfApplication1"

XamlParseException when referencing converter from different assembly

I have a XAML UserControl, which uses a converter contained in the same project.
xmlns:filter="clr-namespace:SampleModuleFilter" - namespace definition
So far so good. However, when I move the converter into another assembly and adjust the namespaces and references accordingly, I get the following exception:
XamlParseException - "Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception. The inner exception states "The method or operation is not implemented." which is just weird.
The namespace after the move into another library looks like this:
xmlns:filter="clr-namespace:SampleLibrary.Converters;assembly=SampleLibrary"
The converter resource definition is:
<filter:BoolToVisibilityConverter x:Key="boolToVisibilityConverter" />
and I use it like so:
Visibility="{Binding DisplayLabel, Converter={StaticResource ResourceKey=boolToVisibilityConverter}}"
IntelliSense can obviously see the library, since it works ok (offers the converter class after I write the namespace prefix).
Any ideas what the problem might be?
You have to reference your assembly also in the code-behind file.
If you reference the assembly only in the XAML part, the compiler returns a "failed to load xxx.dll" exception.
You have also to make a direct call to the connected assembly making something like this:
var dummy = new MyExternalAssemby.MyType();
or just this in a new line of code
new MyExternalAssemby.MyType();
without putting the result in a dummy variable.
Usually I do that in a static constructor.
I think this is a bug in the XAML interpreter because the XAML is not compiled but just "translated" in the BAML (binary XAML). So, if you reference a type in XAML without creating an "hard" reference in the code behind the NET linker ignores it at all.
HTH
Lorenzo
Instead of just:
xmlns:filter="clr-namespace:SampleModuleFilter"
Reference the assembly too
xmlns:filter="clr-namespace:SampleModuleFilter;assembly=SampleModuleFilterAssemblyName"
That should do the trick.
That is strange; we have our converters all located in a central library, and it works fine. Assuming references and namespaces are correct, the only thing I could suggest would be to clean and rebuild the two projects in question.
Is "SampleLibrary.dll" used somewhere in your code ?
I got a strange bug where referenced assemblies only used in xaml file are skipped at compile time, and do not appear in the dll dependencies.

"Prefix 'x' does not map to a namespace"

I want to load a DataTemplate at runtime using XamlReader, but it's throwing the exception "Prefix 'x' does not map to a namespace."
This is the XML string I'm passing to XamlReader:
<xm:ResourceDictionary
xmlns:xm="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:do="clr-namespace:MyLibrary.DataObjects;assembly=MyLibrary.DataObjects"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<xm:DataTemplate DataType="{x:Type do:ValidationResponse}">
<xm:StackPanel Orientation="Horizontal">
<xm:Label>MessageID</xm:Label>
<xm:TextBox Text="{Binding Path=MessageID}"/>
</xm:StackPanel>
</xm:DataTemplate>
</xm:ResourceDictionary>
This is the code that's reading it:
ResourceDictionary dictionary = XamlReader.Parse(myXamlString) as ResourceDictionary;
Here's the funny part, if I add x:Key="ValidationResponseTemplate" to the DataTemplate it parses without any exceptions. I can't keep it that way, however, because I can't specify the DataTemplate by key in the program's own .xaml (it won't know about the template until it gets fetched at runtime).
The x namespace is defined in both the program's own .xaml and in the fragment of XML I'm trying to parse.
Overall objective: be able to provide new DataTemplates to both change the appearance of the display at runtime, and to display XML data that the client did not know about at compile-time.
Found a way around it: rather than have XamlReader parse a string, it worked better if I gave it an XmlReader. The fragment of XML with the DataTemplate defined in it was part of a larger XML document that had all its namespaces defined in its root. This had already been read into an XDocument, and out of which I'd grabbed the XElement with the ResourceDictionary defined in it. The new code, part of MainWindow.xaml.cs, looks like this:
ResourceDictionary dictionary = XamlReader.Load(myXElement.CreateReader()) as ResourceDictionary;
this.Resources.MergedDictionaries.Add(dictionary);
This threw a different exception, where it couldn't resolve the type of (http://myschemas/MyProfile)Binding. It turns out that you need to qualify the namespaces of everything, including the {Binding ...} references. So the XML fragment had to be amended to:
<xm:TextBox Text="{xm:Binding Path=MessageID}"/>
Now XamlParser knew that Binding was a type in the "http://schemas.microsoft.com..." namespace.

Categories