Resource localization: use of x:Uid referring to another assembly's resource - xaml

I am writing a win8 application and will be using the built-in resource management system: resw file and x:Uid tags in my XAML code.
So I create let's say a TextBox like that:
<TextBlock Style="{StaticResource HeaderTextStyle}" x:Uid="ResourceTest"/>
I create the corresponding resource file in my assembly with a ResourceTest.Text entry and it works fine: proper text is displayed at runtime.
Now, I would like to move all my resx files to another C# Library for maintainability. So I put the resources file in a brand new project and reference this new assembly from the main assembly.
But this causes the previous construct to fail (no text is displayed).
However, if I programmatically retrieve the resource value using the following code from inside the side assembly (called ResourcesLibrary), I get the string correctly:
static ResourceLoader resourceLoader = null;
public static string GetString(string resourceName)
{
if (resourceLoader == null)
resourceLoader = new ResourceLoader ("ResourcesLibrary/Resources");
return resourceLoader.GetString (resourceName);
}
How do I enable the x:Uid mechanism when dealing with out-of-assembly resources?
I tried a few things in the x:Uid such as ResourcesLibrary/Resources/ResourceTest but with no luck.

I had the same problem for a long time. But after testing a little bit, I solved it by writing the whole Path of the Resources in the XAML Code.
Something like this:
<TextBlock x:Uid="/ResourcesLibrary/Resources/ResourceTest" />
Unfortunately this answer came very late, but may it can help other persons.

As per my understanding you can't use x:Uid if the resources are maintained in a .resx file.
if you use .resw files you can access the strings whatever the assembly they are residing in.
they can be accessed as you mentioned in your question like this "ResourcesLibrary/Resources/ResourceTest"

Related

How to view the procedural code for any xaml file

I'm working in Visual Studio 2012 with xaml to create an application. When I make a new solution and WPF project and look at the xaml in the application file, I see xmlns, a startupuri, and a tag for application.resources.
When I want to see the code-behind that these tags are creating, I have only the .cs file with maybe a few things in it and the mysterious InitializeComponent() that performs all of the parsing. Here's an example of what it looks like:
public partial class MainWindow : Window //This is generated with a wpf project.
{
public MainWindow()
{
InitializeComponent();
}
}
If possible, how can I view the procedurally generated code that InitializeComponent is creating?
I don't think that the complete xaml source gets compiled into .g.cs files.
Quoting this codeproject article:
When you compile a WPF application in Visual Studio it will compile your XAML files into a compressed representation known as Binary Application Markup Language (BAML). The BAML is then saved as a resource in the resultant assembly. When that assembly is loaded and the resource is requested, the BAML is streamed out and very quickly turned into the object graph described by the original XAML.
In the project directory, under the obj and Debug folders should be files labeled .g.cs that correspond to existing files. Presumably, these are Generated C-Sharp files that contain the generated code that I was looking for.

Loading Loose Xaml with custom controls on WinRT fails unless dummy DataTemplate exists

In ReactiveUI, I run this code at a certain point:
const string template = "<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:routing='using:ReactiveUI.Routing'>" +
"<routing:ViewModelViewHost ViewModel=\"{Binding}\" VerticalContentAlignment=\"Stretch\" HorizontalContentAlignment=\"Stretch\" IsTabStop=\"False\" />" +
"</DataTemplate>";
var theTemplate = XamlReader.Load(template);
On other platforms, this works great (the xmlns declaration is different of course), but on {WinRT / Metro / Windows Store}, this throws an Unspecified Error:
WinRT information: The type 'ViewModelViewHost' was not found. [Line: 1 Position: 253]
The Twist
However, if you include a dummy resource on the page:
<Page.Resources>
<DataTemplate x:Name="Foo">
<routing:ViewModelViewHost ViewModel="{Binding}" />
</DataTemplate>
</Page.Resources>
...then it works! What gives?
The "twist" makes me think this must be because the application does not have correct XAML metadata for the type being instantiated - rather than using reflection to resolve types in XAML files like WPF/Silverlight, WinRT uses code generation to resolve via the IXamlMetadataProvider interface (there's a decent description here; this sounds like what you're doing, see also the followup). Adding the reference forces this metadata code to be generated properly. If this is the case, you should be able to achieve the same effect by simply adding the type itself to the resources under some unused key, without the data template.
Have a look in your application's "obj" directory, Visual Studio generates a XamlTypeInfo.g.cs file to implement IXamlMetadataProvider. This should contain an entry for the type that is failing - in the case where you have added a dummy reference, there should be full details required to instantiate the type. Without this, I've found it's possible to have some reference to type type, but insufficient information - however this prevents the fallthrough behaviour (looking up the type in a dependent DLL which might have a custom metadata provider).
Other than adding a dummy reference to the library type in the final application itself, the only solution I found for this is to apply the Bindable attribute to the type. While this is supposed to relate to C++, I found this can be used in C# to force a type to always appear in the code generated for XAML type metadata.

How efficient is XAML parsing in WinRT / Win8?

When creating UserControls, it looks like the XAML is being parsed every time the control is initialized.
For example, when I create a UserControl, there's auto-generated code to initialize the component that looks like this:
public void InitializeComponent()
{
if (_contentLoaded)
return;
_contentLoaded = true;
global::Windows.UI.Xaml.Application.LoadComponent(this, new global::System.Uri("ms-appx:///Views/MyView.xaml"), global::Windows.UI.Xaml.Controls.Primitives.ComponentResourceLocation.Application);
}
This existed in Silverlight as well.
Creating the control once or twice is not a big deal, but if I have a large visual tree in each UserControl with Visual-States and bindings, and I'm creating it many times per application lifecycle, it would make sense to build the visual controls using C# to boost performance.
So, my question is:
Does the parser/framework "remember" the XAML file and avoid re-parsing it again on subsequent calls? That is, does it create a binary representation of the XAML so it doesn't have to read text all over again?
It's my understanding that XAML gets compiled into a binary form as a resource within your application. The runtime does not have to parse the text of the .xaml file, just as it does not have to parse your .cs code files.
The performance of instantiating the classes as declared with XAML is supposed to be on par with creating it in code.
Windows 8.1 xaml finally added XAML binary format :)
XAML Binary Format: The final signed appx will no longer contain text based markup as it will get converted into Binary.

Using ResourceDictionary from a DLL in Windows 8

How can I use the ResourceDictionary resource from the same DLL?
Basically I am trying to create a UI library with all classes derived from Page class. I want to keep all user interface pages in the same DLL.
To see the problem, from VS2012, create a Windows 8 library project, then add the Item Detailed Page. Now, if you open the created page from the editor, you will get some errors like "The resource "LayoutRootStyle" could not be resolved".
This is just a Xaml Designer error, so that will not prevent your project from building or running .
The only thing needed is that all the ResourceDictonary need to be referenced by the main application App.xaml (for example by using <ResourceDictionary Source="/<myLibraryName>/Common/StandardStyles.xaml"/> or by creating calling an Init method in the Library which will dynamically add the Resource dictionary).
A quick workaround for the error in the Xaml Designer is to just copy an App.xaml/App.xaml.cs in your library (but at runtime the main application will still need to have a reference on the needed ResourceDictionary since the App.xaml of the library will not be used).
Another posibility is to just add a refrence on the ResourceDictionary on each page but I believe that will be much more costly since it will create an instance of the dictionary for each page.

Viewing a BitmapImage for Sample Data in Design Mode in Blend 2012

Is there a way to create a BitmapImage as Sample Data to be used in Blend 2012 Metro Store App (on Windows 8)?
I have a ViewModel as follows:
public ItemDesignDataVM()
{
WebThumbnail = new BitmapImage(new Uri(???));
}
public string ItemId { get { return "123456"; } }
public BitmapImage WebThumbnail { get; private set; }
And would like to bind to it within Xaml like this:
<Page.Resources>
<DesignData:ItemDesignDataVM x:Key="ItemDesignDataVM" />
</Page.Resources>
<TextBox Text="{Binding ItemId}" />
<Image Source="{Binding WebThumbnail}" />
The problem is that no matter what I pass to the BitmapImage constructor it fails to get created. I've tried various different relative paths and an absolute path too.
If I attach to the XDesProc.exe process and debug that code path the BitmapImage.PixelHeight and PixelWidth are 0 which I think means they haven't been loaded.
My binding is correct as I'm seeing the ItemId coming up in the designer.
Any help would be appreciated.
I don't know if that is actual code or pseudo code, but I see a couple issues with what you've posted.
First, your WebThumbnail property doesn't support change notification. Since the property is set in the constructor you should be OK, but if you later decide to make this happen asynchronously then the property could get filled in after binding occurs, and without change notification the UI would never update.
Next, although you've created the ViewModel as a Page resource, I don't see anywhere that you've set it as the DataContext for the page. The ViewModel doesn't necessarily have to be set as a resource, it can be set directly on the DataContext or d:DataContext properties. Since you're saying that you see the ItemId, you either have xaml or code elsewhere to wire this resource up to the DataContext or you may have a default value in the textbox?
As to why the PixelWidth and PixelHeight are zero, maybe you're checking it right after calling the constructor and before the BitmapImage has actually had a chance to download the image data asynchronously? These values may actually get filled in later, but if you're not setting the DataContext of the page properly you would never see the image.
If that's not actually what's going on, you may have an issue with the URL. First, try the URL of a known image online. Make sure the URL works in your browser and then try it in the code. If the URL is for a local file, there are special prefixes you need to use like ms-appx:/// if the file is embedded in your project, ms-appdata:///local/... if it's in your apps local folder, ms-appdata:///roaming/... if it's in your apps roaming folder, etc. (note the 3 slashes).
Hope that helps...