WPF markupExtension only works if it's in the same namespace - wpf

I'm following a tutorial from here:
http://www.wpftutorial.net/LocalizeMarkupExtension.html
and everything works fine....Untill I devide my code in to different projects
So I have a class (TranslateExtension) that inherits from MarkupExtension. this allows me to add markup like this to WPF:
<TextBlock Text="{Mynamespace:Translate key1}" Margin="8" ></TextBlock>
and the textblock gets filled in with the necessary text
But when i want to put the front end in a different project I get the following exceptions:
The name "Translate" does not exist in the namespace
The type "Translate" was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built
The tag "Translate" does not exist in XML namespace ....
I already have added a reference to the namespace on top of my XAML file and the namespace exists inside of the new project. I also have a reference from my Front end to my old project.
So everything works fine untill I extract the front end in to a different project....
IMPORTANT: If I take TranslateExtensions and Put it in the front end, with everything else in the old project, things magically work...
any ideas?

XAML namespaces starting with clr-namespace: are specific to an assembly. If you don't specify the assembly name, the current assembly is assumed.
The simplest option will be to use an assembly-qualified namespace:
xmlns:MyNamespace="clr-namespace:MyNamespace;assembly=MyAssembly"
For a more robust solution, you might want to look at the XmlnsDefinitionAttribute, which can be used to map multiple CLR namespaces across different assemblies to a single XML namespace URI.

Related

Fix XamlObjectWriterException, Cannot create unknown type in F#, FsXaml, WPF app?

I am getting this error in a WPF app that is built with F#, FsXaml, and Elmish.WPF.
System.Xaml.XamlObjectWriterException:
Cannot create unknown type '{http://schemas.componentone.com/winfx/2006/xaml}C1ProgressIndicator'.
at System.Xaml.XamlObjectWriter.WriteStartObject(XamlType xamlType)
at FsXaml.InjectXaml.from(String file, Boolean loadFromResource, Object root)
A Views project contains XAML and includes a reference to C1.WPF.4.dll.
The XAML declares an instance of a control from C1.WPF.4.dll.
However, there is no F# code that uses any types from C1.WPF.4.dll.
Consequently, Views.dll does not contain a reference to C1.WPF.4.dll, as confirmed by IL Spy.
Consequently, when I build App.exe, C1.WPF.4.dll is not included in the output folder.
Consequently, I get a run-time error.
While I could include a reference to C1.WPF.4.dll in my App project, I would rather not.
Is there a better way to do this?
To get this to work:
In your XAML file, replace the XAML namespace with a CLR namespace. For example, instead of xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml" use something like xmlns:c1="clr-namespace:C1.WPF;assembly=C1.WPF.4".
This is required because when App.exe is running, it may not have loaded the controls library yet. It is in the controls library that an attribute creates the mapping from XAML namespace to CLR namespace. By explicitly stating the CLR namespace and assembly, the XamlReader can find the class to instantiate.
Create a dummy instance in the Views code. The dummy instance is an instance of something from the controls library. This creates the dependency in Views.dll on the controls library.
// force the compiler to add a reference to C1.WPF.4.dll
let private forceC1DllReference = C1.WPF.Anchor.TopLeft
type MainWindowView = XAML< "MainWindow.xaml" >
This second one feels like a hack. I wonder if there is a better way to say, "Please add a reference to this DLL even if I'm not using types from it."

XAML Unable to Read Values From Resx file

I have an composite application which has a Shell window and has some modules, each module is loaded on to the shell using MEF (Microsfot Prism). Shell Itself has a resource file default(Resource.resx) and for other languages(like Resource.ar-SA.resx) too to support Localilzation.
For Xaml : I had used x:Static Resource.KeyName
In c# Code : I had used GetString(keyName, culture) to get the required string.
To support Localization, I have added a line of code which gets the current culture of the system and loads the required Resx File.
For Setting the Current Culture.
Resource.Culture =
new System.Globalization.CultureInfo(System.Globalization.CultureInfo.CurrentCulture.Name);
in App.Xaml.cs
All these work Completely fine.
Similarly, each module which is loaded using MEF has Resource files as mentioned above. But in case of Modules, resource Key defined in the Xaml for a specific language file is not working. Its always getting the values from the Default (Resource.Resx) file. But any key used in the code using ResourceManager class works fine.
I ended up keeping all my resources in an "Infrastructure" project so all the resources are loaded from one place, it just made it simpler.
My xaml bindings look like this
Get the refrence to your resx class.
xmlns:resources="clr-namespace:Infrastructure.resources;assembly=Infrastructure"
now get the text
Content="{x:Static resources:Resources.Activity_Regarding}"
You might be doing this already but I cant see. You would want to make sure the namespace matches for the resx you want to use. So your modules namespace.

XAML Resx localization not working as expected

I'm attempting to use a resx file to localize some strings I am using in a XAML file. I've looked around at other documentation on the web, and they all seem to recommend a two part process:
Add a clr-namespace to your window, like this:
xmlns:props="clr-namespace:PJConfiguration.Properties"
Use that namespace to localize your string like this:
Content="{x:Static props:Resources.SharedSettings}"
I've done this, and also made sure that my resource classes are public, but I still get the following error from the XAML in step 2:
Cannot find the type 'Resources'.
Does anyone know what else might be causing this problem? Thanks in advance.
In order to make the Resources visible to XAML, you have to make sure that the code generation mode for the resources is set to public. In VS, you find that setting in a ComboBox near the top of the Resources designer window.
For more information on using .Net resources in XAML, you might want to refer to these blog posts: http://wpfglue.wordpress.com/category/localization/
Check if your .resx file is the default Resources.resx file inside the Properties directory of the Application assembly. If that is, there is no reason XAML couldn't find the public class Resources from the correct namespace under local assembly.
Try to specify the assembly name in Step 2 as recommended in this answer.

Remove an old namespace from a g.cs File?

I previously had a subfolder in my WPF application project called "Controls". It contained a WPF user control. I decided to move that user control to my "Views" folder. Since the original folder was empty, I decided to delete it from the project.
Because the user control and folder is removed I receive a compilation error because the user control used the ProjectName.Folder namespace and now nothing references it. MainWindow.g.cs is what references ProjectName.Controls in a using statement.
I know that *.g.cs are generated by VS and can't be edited because it will be overwritten. What do I do to not allow that namespace to be written to the g.cs file? I tried cleaning my solution/project and rebuilding but nothing has worked.
I had a local reference to the Controls namespace in my Xaml code (MainWindow.xaml). I removed the reference, cleaned the project and produced a successful build.
In your user control file,
In your ClassName.xaml, you must change the namespace as shown below
<UserControl
x:Class="YourOldNamespace.ClassName"
...
...
/>
And in your ClassName.xaml.cs, you must change the namespace as shown below
using System;
using System.Windows;
namespace YourOldNamespace{
public class ClassName{ ....
}
In both the files, you must replace YourOldNamespace to some new namespace as needed.
I have had problems with g.cs files in my projects before too. Since they are auto generated, I tend to just delete the file manually and rebuild.
Dont forget too, that you must check to see if the Build Action property when you click on the affected XAML file is set to PAGE (instead of resource). This is useful to know when you copy a XAML from another project using copy-paste to save time.
Also look at App.xaml and all of your resource dictionaries. For whatever reason, VS 2012's replace in files / "Entire Solution" option didn't find the old namespace reference in App.xaml, had to manually change that. Fixed it for me.
Don't forget to change your Generic.xaml file too,
<ResourceDictionary
xmlns:local="clr-namespace:MyOldNameSpace">
</ResourceDictionary>

Loose xaml referencing versioned assemblies

I have a unique development situation and would like some input from others.
I have a situation where I need to load loose xaml files within a rich client application.
A given loose xaml file may have references to an assembly not currently loaded in memory
so the referenced assembly is loaded before the loading the loose xaml. The loose xaml and tied
assemblies are stored on different backend servers which are downloaded to the client and
loaded dynamically.
The loose xaml and/or assemblies are version specific and unfortunately the application can
not be shutdown between rendering xaml.v1 with assembly.v1 from server A
and xaml.v1 with assembly.v2 on server B.
Both assemblies use the same namespace declaration so "older" assemblies can still
work with "newer" ones for any given loose xaml.
The problem is, I do not get a reference to assembly.v2 if I load xaml.v2 which contains
references to "newer" features in assembly.v2.
I obviously cannot unload assembly.v1 from the app domain and I'm not sure if I can
reference items in xaml that are loaded within a different app domain through marshalling.
Any Ideas other than using different namespace references?
I'm guessing that you are already doing dynamic assembly resolution and loading? If so, then you could try substituting a fake assembly name in place of the real assembly name i n the Xaml - you can then use that in your assembly resolution code to load up and return the right assembly. e.g. if your original source Xaml is:
xmlns:myassembly="clr-namespace:MyApp.MyAssembly;assembly=MyAssembly"
and you know that Xaml wants v2 of MyAssembly, replace the assembly ref in the Xaml string before parsing it to:
xmlns:myassembly="clr-namespace:MyApp.MyAssembly;assembly=MyAssembly.v2"
.. then in your assembly resolution / load code, when you see the ".v2" bit on the end you look for and load that assembly instead.
Please let me know if I've misunderstood the question, or you aren't current doing any custom assembly resolution - that would certainly be the key in this situation I think.
Another option (assuming that you are versioning your assemblies properly) is to simply include the assembly version in the ns declaration, like so:
xmlns:ns0="clr-namespace:MyCompany.MyProject.MyNameSpace; Assembly=MyCompany.MyProject, Version=1.0.0.0"
I haven't confirmed if this would work, but I believe that it may. You could use the XmlnsDefinitionAttribute (at assembly level). E.g.
Assembly V1 -> AssemblyInfo.cs
[assembly: XmlnsDefinition( "http://schema.mycompany.com/myproject/v1", "MyCompany.MyProject" )]
Assembly V2 -> AssemblyInfo.cs
[assembly: XmlnsDefinition( "http://schema.mycompany.com/myproject/v2", "MyCompany.MyProject" )]
And then in xaml:
xmlns:myassembly="http://schema.mycompany.com/myproject/v2"

Resources