View Issue Details

IDProjectCategoryView StatusLast Update
0003635NoesisGUIUnitypublic2024-10-23 16:27
Reportersamc Assigned Tomaherne  
PrioritynormalSeverityfeature 
Status resolvedResolutionfixed 
Product Version3.2.3 
Target Version3.2.5Fixed in Version3.2.5 
Summary0003635: Using LocExtension as a Setter value
Description

We would like to be able to use LocExtension as a setter value. would this be possible?

https://www.noesisengine.com/forums/viewtopic.php?p=16876

PlatformWindows

Activities

maherne

maherne

2024-08-20 12:23

developer   ~0009893

Hi Sam,

We're still looking into a solution for using LocExtension in a Setter Value, we'll report back as soon as we have more info.

maherne

maherne

2024-09-05 19:45

developer   ~0009950

Hi Sam,

I have attached an updated LocExtension for Unity3d which supports Setter Values.

This file should replace the existing version in the Unity plugin folder Runtime\API\Localization.

If you could report back on whether this works in all of your intended applications, that would be appreciated.

LocExtension.cs (6,894 bytes)   
using Noesis;
using System;

namespace NoesisGUIExtensions
{
    /// <summary>
    /// Implements a markup extension that supports references to a localization ResourceDictionary.
    ///
    /// Provides a value for any XAML property attribute by looking up a reference in the
    /// ResourceDictionary defined by the Source attached property. Values will be re-evaluated when
    /// the Source attached property changes.
    ///
    /// If used with a string or object property, and the provided resource key is not found, the
    /// LocExtension will return a string in the format "<Loc !%s>" where %s is replaced with the key.
    ///
    /// A Converter can also be specified, with an optional ConverterParameter.
    ///
    /// This example shows the full setup for a LocExtension. It utilizes the RichText attached
    /// property to support BBCode markup in the localized strings. The Loc.Source property references
    /// the "Language_en-gb.xaml" ResourceDictionary below.
    ///
    /// Usage:
    ///
    ///    <StackPanel
    ///      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ///      xmlns:noesis="clr-namespace:NoesisGUIExtensions"
    ///      noesis:Loc.Source="Language_en-gb.xaml">
    ///      <Image Source="{noesis:Loc Flag}"/>
    ///      <TextBlock noesis:RichText.Text="{noesis:Loc SoundLabel}"/>
    ///      <TextBlock noesis:RichText.Text="{noesis:Loc TitleLabel, Converter={StaticResource CaseConverter}, ConverterParameter=UpperCase}"/>
    ///    </StackPanel>
    /// 
    /// This is the contents of a "Language_en-gb.xaml" localized ResourceDictionary:
    ///
    /// Usage:
    ///
    ///    <ResourceDictionary
    ///      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ///      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    ///      xmlns:sys="clr-namespace:System;assembly=mscorlib">
    ///      <ImageBrush x:Key="Flag" ImageSource="Flag_en-gb.png" Stretch="Fill"/>
    ///      <sys:String x:Key="TitleLabel">[b]Localization Sample[/b]</sys:String>
    ///      <sys:String x:Key="SoundLabel">A [i]sound[/i] label</sys:String>
    ///    </ResourceDictionary>
    ///
    /// </summary>
    [ContentProperty("ResourceKey")]
    public class LocExtension : MarkupExtension
    {
        private string _resourceKey;
        private IValueConverter _converter;
        private object _converterParameter;

        public LocExtension()
        {
        }

        public LocExtension(string resourceKey)
        {
            _resourceKey = resourceKey;
        }

        /// <summary>
        /// Gets or sets the key to use when finding a resource in the active localization ResourceDictionary. 
        ///
        /// Usage:
        ///
        ///    <Grid
        ///        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        ///        xmlns:noesis="clr-namespace:NoesisGUIExtensions"
        ///        noesis:Loc.Source="Locale_fr.xaml">
        ///        <TextBlock Text="{noesis:Loc Title}"/>
        ///        <Image Source="{noesis:Loc IntroBackground}"/>
        ///    </Grid>
        ///
        /// </summary>
        public string ResourceKey
        {
            get { return _resourceKey; }
            set { _resourceKey = value; }
        }

        /// <summary>
        /// Gets or sets a converter to use when finding a resource in the active localization ResourceDictionary.
        /// </summary>
        public IValueConverter Converter
        {
            get => this._converter;
            set => this._converter = value;
        }

        /// <summary>
        /// Gets or sets an optional converter parameter to use when finding a resource in the active localization ResourceDictionary.
        /// </summary>
        public object ConverterParameter
        {
            get => this._converterParameter;
            set => this._converterParameter = value;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            IProvideValueTarget valueTarget = serviceProvider as IProvideValueTarget;
            if (valueTarget == null)
            {
                return null;
            }

            Binding binding = new Binding
            {
                Path = new PropertyPath($"({GetType().FullName}.Resources)[{ResourceKey}]"),
                RelativeSource = valueTarget.TargetObject is FrameworkElement ? RelativeSource.Self :
                    new RelativeSource(RelativeSourceMode.FindAncestor, typeof(FrameworkElement), 1),
                Converter = Converter,
                ConverterParameter = ConverterParameter
            };

            return binding.ProvideValue(serviceProvider);
        }

        #region Source attached property

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.RegisterAttached(
                "Source",
                typeof(Uri),
                typeof(LocExtension),
                new PropertyMetadata(null, SourceChangedCallback)
            );

        private static void SourceChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Uri source = (Uri)d.GetValue(SourceProperty);

            if (source == null)
            {
                d.ClearValue(ResourcesProperty);
                return;
            }

            ResourceDictionary resourceDictionary = new ResourceDictionary
            {
                Source = source
            };

            d.SetValue(ResourcesProperty, resourceDictionary);
        }

        public static Uri GetSource(UIElement target)
        {
            return (Uri)target.GetValue(SourceProperty);
        }

        public static void SetSource(UIElement target, Uri value)
        {
            target.SetValue(SourceProperty, value);
        }

        #endregion

        #region Resources attached property

        public static readonly DependencyProperty ResourcesProperty =
            DependencyProperty.RegisterAttached(
                "Resources",
                typeof(ResourceDictionary),
                typeof(LocExtension),
                new FrameworkPropertyMetadata(null, flags: FrameworkPropertyMetadataOptions.Inherits)
            );

        public static ResourceDictionary GetResources(DependencyObject dependencyObject)
        {
            return (ResourceDictionary)dependencyObject.GetValue(ResourcesProperty);
        }

        public static void SetResources(DependencyObject dependencyObject, ResourceDictionary resources)
        {
            dependencyObject.SetValue(ResourcesProperty, resources);
        }

        #endregion
    }
}
LocExtension.cs (6,894 bytes)   
samc

samc

2024-09-10 21:15

reporter   ~0009964

Thank you so much. We are giving this a shot and will report back.

samc

samc

2024-09-17 18:19

reporter   ~0009972

This appears to be working great!

Issue History

Date Modified Username Field Change
2024-08-16 00:35 samc New Issue
2024-08-16 17:05 sfernandez Assigned To => maherne
2024-08-16 17:05 sfernandez Status new => assigned
2024-08-16 17:05 sfernandez Target Version => 3.2.5
2024-08-20 12:23 maherne Note Added: 0009893
2024-09-05 19:45 maherne Note Added: 0009950
2024-09-05 19:45 maherne File Added: LocExtension.cs
2024-09-05 19:45 maherne Status assigned => feedback
2024-09-10 21:15 samc Note Added: 0009964
2024-09-10 21:15 samc Status feedback => assigned
2024-09-11 14:51 maherne Status assigned => feedback
2024-09-17 18:19 samc Note Added: 0009972
2024-09-17 18:19 samc Status feedback => assigned
2024-10-23 16:27 maherne Status assigned => resolved
2024-10-23 16:27 maherne Resolution open => fixed
2024-10-23 16:27 maherne Fixed in Version => 3.2.5
2025-10-10 13:29 jsantos Category Unity3D => Unity