XamlParseException when referencing converter from different assembly - c#

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.

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

Unable to cast HttpRequestMessage.Properties["MS_RequestContext"] as OwinHttpRequestContext at build time but valid at runtime

I'm trying to manually fiddle with a property of my MS_RequestContext during Controller Activation inside my WebApi's CompositionRoot.
My Create method receives a System.Net.Http.HttpRequestMessage argument.
I can drill down request to grab
request.Properties["MS_RequestContext"]
Properties is a dictionary<string,object> That object will be an OwinHttpRequestContext at runtime.
But whenever I attempt to cast, so that I can access the properties on the RequestContext, I get a nasty-gram from Visual Studio
(request.Properties["MS_RequestContext"] as OwinHttpRequestContext).Request.Properties;
The error that comes back is:
The type or namespace 'OwinHttpRequestContext' could not be found (are you missing a using directive or an assembly reference?)
OwinHttpRequestContext lives inside the System.Web.Http.Owin namespace. My references are all set up. I even have added a using statement for good measure.
So the crazy part is that if I roll back my code that attempts to directly reference request.Properties, but instead set a breakpoint inside my Create method, I can -through a watch- execute
(request.Properties["MS_RequestContext"] as System.Web.Http.Owin.OwinHttpRequestContext).Request.Properties
without issue. I can confirm that I have no problem modifying the properties at runtime through the immediate window.
(request.Properties["MS_RequestContext"] as System.Web.Http.Owin.OwinHttpRequestContext).Request.Properties.Add("Foo","Bar")
And the property "Foo" will be available to all of my MessageHandlers.
Why am I not able to perform this same cast at build time?
OwinHttpRequestContext is not a public class. That is why you can't use it in code, but debugger can still see it.

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"

Lambda expression create unrelated compile error

Whenever I add a lambda expression (in the following form) to my wpf project, I get an error. The errors are nothing to do with the expression, but they arrive every time I add one.
here is my latest:
using ( LeisureServiceClient client = ServiceFactory.Instance.GetLeisureService() )
{
client.Execute( ServiceFactory.Instance.ConnectionDetails, new MoveBasketItemsToAccountCommand()
{
BasketItemIDs = bisList.ToList().ConvertAll<Guid>( bis => bis.ID )
} );
}
This seems perfectly valid to me, this gives the following compile error, highlighting client from client.Execute(...).
Error 43: The type 'System.Windows.DependencyObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
this code is nothing to do with a DependancyObject. Regardless, System.Windows is referenced in the .cs file, which also contains:
public class PointOfSaleViewModel : DependencyObject
which is quite happy to compile when the lambda expression is removed.
now, to add confusion... this is fine:
ServiceFactory.Instance.ShiftDataRefreshedEvent += ( s, e ) =>
{
Account = new ObservableCollection<BasketItemSummary>( ServiceFactory.Instance.CurrentContact.Account );
Basket = new ObservableCollection<BasketItemSummary>( ServiceFactory.Instance.Shift.OpenCurrentContact.Basket );
};
so, it's not the lambda expression itself that's causing the error, I'm out of ideas as to why this isn't compiling, and pretty keen to get some input before my head explodes.
Update
the alternate syntax suggested by a colleague
BasketItemIDs = bisList.ToList().ConvertAll( delegate( BasketItemSummary basketItem ) { return basketItem.ID; } )
also fails, giving the same compilation error.
It sounds to me like BasketItemSummary (or one of the properties) exposes this dependency on the public API - perhaps it is a base-class for the type. Simply: add the missing reference as it instructs.
I know this question is old, but in case someone else faces this problem:
Recently, I faced a problem much like yours. The solution I'm working includes a web project which has reference to a wpf project (for generating documents for downloading). After some modifications in the wpf project, the web project would not compile anymore, with the following error message:
Error 4 The type 'System.Windows.DependencyObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
After some debugging, I figured out the error message only pointed to lines which involved LINQ operations (first I also thought it was related to lambdas, as you).
In the end, the root of the problem were some wpf's visual tree helper methods I had taken from http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/. I had taken the methods from LinqToVisualTree and put them under the "System.Linq" namespace. Seemingly that was somehow conflicting with the original Linq extension methods in my web project, and once I changed the namespace of the LinqToVisualTree methods to something else the problem went away.
You need to add a reference to the dll in your project: right click on project, choose add reference.

Alias and namespace conflict in Visual Studio Designer

I have a namespace conflict between two referenced assemblies:
i.e., I'm referencing Foo.A.Foo and Foo.Bar, so when I say I want Foo.Bar.Control, VS is trying to find Foo.A.Foo.Bar.Control
I can twiddle the Designer.cs code by adding new global:Foo.Bar.Control(), but as soon as I change anything, VS switches back.
I know there's something about adding aliases directly to the reference, I've tried but haven't managed to find the right combination (inline alias, using alias, reference alias).
Help?
"extern alias" may be what you mean, but I'm not sure what the designer will do with it, unfortunately...
I'm not even sure that's what you're after though - that's normally for two types from different assemblies with the same name.
You can write namespace aliases with a using directive, e.g.
using FooControl = Foo.Bar.Control;
but again, the designer is going to rewrite your code...
OK, this isn't the answer, but it's what I found for a workaround:
namespace FooBar
{
class FooBarControlHack : Foo.Bar.Control { }
}
So I can do the following in the Designer.cs :
this.fooBarControl = new FooBar.FoorBarControlHack();

Categories