So I'm attempting to add localization to the UWP application I'm working on. From what I've researched online I'm able to add it using the Mulitlingual App Toolkit. The one issue I run into is duplicate values in the resource file. For example imagine I need to label 2 different controls with the same value. The controls are a button (using the property button.Content) and a text block (using textBlock.Text). I'd like to only have one name/value pair in the resource file that can be used for both of these controls. Is there a way to do this? Also I'd like to be able to set these values in xaml. Thanks in advance.
Localization for UWP in general
First, the default way of internationalization (i18n) and localization (l10n) is by using different .resw (or .resx for other environments like Xamarin) per language. In these files you store translated strings with some identifier key.
The Mulitlingual App Toolkit is a tool to facilitate and somewhat manage (e.g. tracking review status) the surrounding processes of actually translating the strings with people that possibly are not part of the actual dev team. But in the end, it too just generates the .resw files like you could have done manually. So you don't HAVE to use the MAT in order to localize your App.
Implementing it
The way to achieve what you want would be to use some sort of Binding.
I personally like to use a custom markup extension to be able to distinguish between actual dynamic data and hardcoded internationalized strings. Furthermore it keeps the Binding short. This would then look something like Title="{i18n:Translate GlossaryPageTitle}".
Unfortunately, Markup Extensions don't seem to be available in UWP as of yet (source).
So the way to go (simpler anyway) is to use a Converter and pass the Key for the desired Text as a parameter.
Like this:
Title="{x:Bind Converter={StaticResource LocalizationConverter}, ConverterParameter=GlossaryPageTitle}".
Where the implementation of the converter would look like this:
public class LocalizationConverter : IValueConverter
{
private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForViewIndependentUse("/Resources");
public object Convert(object value, Type targetType, object parameter, string language)
{
if (parameter is string resourceId)
{
return _resourceLoader.GetString(resourceId);
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotSupportedException();
}
}
Then register the Converter somewhere in your App (either per view or globally) and you're good to go.
Related
I've got 2 Pages: My Main-Page and my Settings-Page - both in XAML and xaml.cpp as code behind. I've also got a class where I want to work with the values of the Settings-Class. (As I already asked in another post) I can save the values from the Settings-Page in the cache using the XAML-tag NavigationCacheMode="Enabled". Using this my SliderValue stays the same even when I switch to my Main-Page and back again to Settings-Page.
What I want to do now: Save the value of the slider as soon as it is changed and store this value to a variable to which I have access from a third Class.
What I've got so far (not working, always showing initialvalue '70'):
Settings.xaml.cpp:
UWPApp::Settings::Settings()
{
InitializeComponent();
quality = sldQuality->Value;
}
int Settings::getQuality() {
return quality;
}
void DirectX12XamlApp::Settings::sldQuality_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
quality = sldQuality->Value;
}
In Settings.xaml.h:
public:
Settings();
int getQuality();
private:
int quality;
In Settings.xaml:
<Slider x:Name="sldQuality" ValueChanged="sldQuality_ValueChanged" HorizontalAlignment="Left" Margin="38,325,0,0" VerticalAlignment="Top" Width="168" Value="70"/>
//initial-Value = 70, which is ALWAYS showing when using getQuality() in an other Class
In my logicclass I want to use it like this:
int quality = Settings::getQuality();
Quick answer: save the value of the slider in a public static property, ideally in the separate class.
Recommended answer:
You should use MVVM structure in your app, so you would have a separate layer for storing your settings data. You can save the value of the slider in the singleton service, ideally injected through the IoC container. You may also want to save it in the local storage so the settings are saved when the user closes the app.
MVVM is really a standard of XAML-based apps, and the concept is not difficult to learn and implement.
Sounds like you're looking for a way to store and retrieve settings data for your app. Features for that have been built into the UWP. Please refer to this article from the Windows Dev Center. Examples on that page are for C#, but all the links to UWP API references contain code snippets for C++ as well.
I want to encapsulate frame navigation in custom command und use this command declaratively as a static ressource. I found
Frame.Navigate(typeof(MainPage));
which expects a type parameter (type of the target page) to navigate to. My first attempt was to use a generic ICommand implementation that passes the type of the target page as generic type parameter. As of x:TypeArguments is not supported for Windows Store Apps, I tried to define a property
public Type TargetType { get; set; }
for the command. But no luck again: if I try to set the property via a xaml attribute
`<NavigationCommand TargetType="MainPage">
I get a compile-time error saying
MainPage is not supported in a Windows universal project
This should work:
<NavigationCommand TargetType="ns:MainPage">
Where ns is an XML namespace prefix declared with xmlns:ns="using:TheNamespaceInCode"
(note: the x:Type markup extension used in WPF isn't supported in WinRT)
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"
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.
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...