0

I am trying to implement a localization so when the language is changed by the user, everything changes in runtime.

I have the next class LocalizedResources:

public class LocalizedResources : INotifyPropertyChanged
{
    const string DEFAULT_LANGUAGE = "";

    readonly ResourceManager ResourceManager;
    CultureInfo CurrentCultureInfo;

    public string this[string key]
    {
        get => ResourceManager.GetString(key, CurrentCultureInfo);
    }

    public LocalizedResources(Type resource, string language = null)
        : this(resource, new CultureInfo(language ?? DEFAULT_LANGUAGE))
    { }

    public LocalizedResources(Type resource, CultureInfo cultureInfo)
    {
        CurrentCultureInfo = cultureInfo;
        ResourceManager = new ResourceManager(resource);

        MessagingCenter.Subscribe<object, CultureChangedMessage>(this,
            String.Empty, OnCultureChanged);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnCultureChanged(object s, CultureChangedMessage ccm)
    {
        CurrentCultureInfo = ccm.NewCultureInfo;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item"));
    }

    public string CurrentCulture() => CurrentCultureInfo.Name;

    public CultureInfo CurrentCultureI() => CurrentCultureInfo;
}

When I use it directly in a view binding (like {Binding Resources[key]}, an example of it is below), it works wonders, but I have few cases when I have to create another property in another model using this class. An example:

public class MediaViewModel : BaseViewModel
{

    public CultureInfo localization;
    public int localizationFirstDay;
    
    public MediaViewModel()
    {
        localization = Resources.CurrentCultureI();
        localizationFirstDay = (int)Resources.CurrentCultureI().DateTimeFormat.FirstDayOfWeek;
    }

}

Here I save Resources.CurrentCultureI(); in localization to use it in its view:

                    <StackLayout Padding="5, 10, 5, 10">
                    <calendar:SfCalendar x:Name="calendar" 
                                         ViewMode="MonthView" 
                                         YearViewMode="Month" 
                                         Margin="10, 5, 10, 5"
                                         NavigationDirection="Vertical"
                                         ShowInlineEvents="True"
                                         InlineViewMode="Agenda"
                                         VerticalOptions="FillAndExpand"
                                         Locale="{Binding localization}"
                                         FirstDayofWeek="{Binding Resources[LocalizationFirstDay]}">
                        <calendar:SfCalendar.MonthViewSettings>
                            <calendar:MonthViewSettings>
                                <calendar:MonthViewSettings.InlineItemTemplate>
                                    <DataTemplate>
                                        <Button AutomationId="{Binding AutomationId}" 
                                                Text="Texto" TextColor="#bbd5ed"/>
                                    </DataTemplate>
                                </calendar:MonthViewSettings.InlineItemTemplate>
                            </calendar:MonthViewSettings>
                        </calendar:SfCalendar.MonthViewSettings>
                    </calendar:SfCalendar>
                </StackLayout>

FirstDayofWeek="{Binding Resources[LocalizationFirstDay]}" works fine, but Locale="{Binding localization}" does not.

How can I solve it?

Cfun
  • 8,442
  • 4
  • 30
  • 62
Soondra
  • 19
  • 1
  • localization must be a property not a field for INotifyPropertyChanged to work. Try changing to `public CultureInfo localization { get; set; }` – Cfun Jan 20 '21 at 21:27
  • Does this answer your question? [Why does WPF support binding to properties of an object, but not fields?](https://stackoverflow.com/questions/842575/why-does-wpf-support-binding-to-properties-of-an-object-but-not-fields) – Cfun Jan 20 '21 at 21:35
  • It might have to do with that post, but still changinc localization form field to object does not solve my problem... – Soondra Jan 21 '21 at 16:21

1 Answers1

0

localization is getting a new value in the constructor, use OnPropertyChanged("localization") or RaisePropertyChanged("localization") or any method you are using in your BaseViewModel to make the binding aware of the change.

public class MediaViewModel : BaseViewModel
{
    private CultureInfo _localization
    public CultureInfo localization{
      get{return _localization;}
      set{_localization = value; OnPropertyChanged("localization");}
     }
    public int localizationFirstDay;
    
    public MediaViewModel()
    {
        localization = Resources.CurrentCultureI();
        localizationFirstDay = (int)Resources.CurrentCultureI().DateTimeFormat.FirstDayOfWeek;
    }

}

gadnandev
  • 104
  • 3
  • Thanks for the reply, but it doesn't work for me. I'm not sure wheter OnCultureChanged (event raised from LocalizedResources) reaches de model class so it can set the new location. Could it be the problem? – Soondra Jan 21 '21 at 16:40