Want to dynamically multilingualize with WPF attachment properties

Asked 2 years ago, Updated 2 years ago, 127 views

When I looked at WPF multilingual, I found some samples of dynamic switching, but the description in the XAML was likely to be enlarged, so I made it multilingual in the attached properties, but changing the culture from the button on the screen did not change the text on the screen.

Because the multilingual processing is done in the OnTextChanged part of the attached property, I know that the language will not switch unless the OnTextChanged event does not work, but I couldn't think of a solution.
Please let me know if there is a way to switch between OnTextChanged events when changing the culture.

MV Caliburn.Micro is used as the MVVM library

Attachment Properties

public class MultilingualText
{
    public static dependencyProperty MultilingualTextProperty
        = DependencyProperty.RegisterAttached("Text",
            type of (string),
            type of (MultilingualText),
            new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnTextChanged)));

    public static void SetText (DependencyObjectobj, string value)
        =>obj.SetValue (MultilingualTextProperty, value);

    public static string GetText (DependencyObject obj)
        =>(string) obj.GetValue(MultilingualTextProperty);

    private static void OnTextChanged (DependencyObject obj, DependencyPropertyChangedEventArgse)
    {
        if(obj is TextBlock textblock)
        {
            // Obtain strings from Resources that are tied to the current culture
            textblock.Text=Properties.Resources.ResourceManager.GetString(e.NewValue.ToString(), CultureService.Current.GetCurrentCulture());
        }
    }
}

Calature Class

class CultureService:PropertyChangedBase
{
    public static CultureService Current {get;} = new CultureService();
    /// <summary>
    /// Get multilingual resources
    /// </summary>
    private CultureInfo_Resources;
    public CultureInfo Resources
    {
        get {return_Resources;}
        set {this.SetProperty(ref_Resources, value);}
    }

    /// <summary>
    /// Change the Cultures
    /// </summary>
    public void ChangeCulture (string name)
    {
        Resources=CultureInfo.GetCultureInfo(name);
    }

    /// <summary>
    /// Get a Carture
    /// </summary>
    public CultureInfo GetCurrentCulture()
    {
        return Resources;
    }
}

XAML

<Grid>
    <TextBlock local: MultilingualText.Text="HelloWorld"/>
</Grid>

Button Events

private void Button1_Click (object sender, RoutedEventArgse)
{
    CultureService.Current.ChangeCulture("ja-JP";
}
private void Button2_Click(object sender, RoutedEventArgse)
{
    CultureService.Current.ChangeCulture("en-US";
}

wpf xaml

2022-09-30 14:14

1 Answers

I tried to do this by registering PropertyChanged event monitoring for CultureService.Current in MultilingualText.OnTextChanged().
We use weak event patterns to avoid memory leaks.

public class MultilingualText
    {
        private static readonly DependencyProperty WeakEventListenerProperty
             = DependencyProperty.RegisterAttached("WeekEventListener",
                 type of (IWeekEventListener),
                 type of (MultilingualText),
                 new PropertyMetadata (null));

        private static void SetWeekEventListener (DependencyObjectobj, IWeekEventListener value)
            =>obj.SetValue (WeekEventListenerProperty, value);

        private static IWeekEventListener GetWeekEventListener (DependencyObjectobj)
            =>(IWeekEventListener) obj.GetValue(WeekEventListenerProperty);


        public static dependencyProperty MultilingualTextProperty
            = DependencyProperty.RegisterAttached("Text",
                type of (string),
                type of (MultilingualText),
                new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnTextChanged)));

        public static void SetText (DependencyObjectobj, string value)
            =>obj.SetValue (MultilingualTextProperty, value);

        public static string GetText (DependencyObject obj)
            =>(string) obj.GetValue(MultilingualTextProperty);

        private static void OnTextChanged (DependencyObject obj, DependencyPropertyChangedEventArgse)
        {
            InitializeEventListner(obj);
            UpdateText(obj);
        }


        private static void UpdateText (DependencyObjectObj)
        {
            if(obj is TextBlock textblock)
            {
                // Obtain strings from Resources that are tied to the current culture
                textblock.Text=Properties.Resources.ResourceManager.GetString(GetText(obj), CultureService.Current.GetCurrentCulture());
            }
        }

        private static void InitializeEventListner (DependencyObject obj)
        {
            if(GetWeekEventListener(obj)!=null)return;

            var propertyChangedListener=new PropertyChangedWeakEventListener(obj, RaisePropertyChanged);
            PropertyChangedEventManager.AddListener(CultureService.Current, propertyChangedListener, nameof(CultureService.Resources));
            SetWeekEventListener(obj, propertyChangedListener);
        }

        private static void RaisePropertyChanged (DependencyObjectObj, string propertyName)
        {
            UpdateText(obj);
        }


        class PropertyChangedWeakEventListener —IWeakEventListener
        {
            private DependencyObject_obj;
            private Action<DependencyObject, string>_risePropertyChangedAction;

            public PropertyChangedWeakEventListener (DependencyObject object, Action<DependencyObject, string>raisePropertyChangedAction)
            {
                _obj=obj;
                _raisePropertyChangedAction=raisePropertyChangedAction;
            }

            public bool ReceiveWeakEvent(Type managerType, object sender, EventArgse)
            {
                if(typeof(PropertyChangedEventManager)!=managerType)
                {
                    return false;
                }

                if(eisPropertyChangedEventArgsevt)
                {
                    _raisePropertyChangedAction(_obj,evt.PropertyName);
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

    }


2022-09-30 14:14

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.