VladislavAntonyuk / MauiSamples

.NET MAUI Samples
https://vladislavantonyuk.azurewebsites.net/articles?categoryName=.NET%20MAUI/Xamarin
MIT License
740 stars 188 forks source link

Maui Localisation: Binding the Key of the string #206

Closed SonOfKorriban closed 1 year ago

SonOfKorriban commented 1 year ago

i am currently trying to implement your Markup Extention for translating strings via the AppResources, as you explained it here.

I can successfully use the Markup Extention in that way: EigenschaftName="{xamlExt:Translate String10423}"

But now i got a Problem. The control where i use that code, is within a DataTemplate. That template is within a CollectionView. You already got it, i think. I need to Bind the Key of the string to the underlying object.

How do i do this? I made a screenshot here: (Just have a look at row 39, where i need the Binding)

grafik

VladislavAntonyuk commented 1 year ago

You can use Code behind and pass translated value from your ViewModel. So your Characteristics.EigenschaftName = LocalizationResourceManager.Instance["Intro"].ToString(); Or you can create a TranslationConverter:

public object Convert(object value ....)
{
     return LocalizationResourceManager.Instance[value].ToString();
}
SonOfKorriban commented 1 year ago

I already tried the Converter, but the UI does not update using that, unfortunately

VladislavAntonyuk commented 1 year ago

could you please share a link to github public repo so I can reproduce it?

SonOfKorriban commented 1 year ago

I can't since, i would need to write a entire solution only for this Problem. Sorry, i don't want to have my entire code public^^. But i can share all imprtant code-parts with you here:

The whole XAML-Code of the Collection View, with "EigenschaftName" as the most important Property. It's binded to the underlying Property "NameStringKey" of the Object (typeof Characteristic) The Whole Collection has as a Item Source a ObservableCollection typeof Characteristic.

         <CollectionView Grid.Row="3" x:DataType="local:MainViewModel" ItemsSource="{Binding Characteristics}"
                    ItemsLayout="HorizontalList" BackgroundColor="#b7ab95">            
            <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="models:Characteristic">
                <Border Margin="5" StrokeShape="RoundRectangle 15 15 15 15" StrokeThickness="0"
                        Background="Transparent">
                    <xamlExt:CharacteristicEntry    
                        Grid.Column="0"
                        HeightRequest="{OnPlatform {StaticResource CharacteristicHeight}, Android={StaticResource CharacteristicHeightAndroid}}"
                        BgHeightRequest="{OnPlatform {StaticResource CharacteristicHeight}, Android={StaticResource CharacteristicHeightAndroid}}"
                        FontSizeValue="{OnPlatform {StaticResource CharacteristicFontSizeValue}, Android={StaticResource CharacteristicFontSizeValueAndroid}}"
                        FontSizeTitle="{OnPlatform {StaticResource CharacteristicFontSizeTitle}, Android={StaticResource CharacteristicFontSizeTitleAndroid}}"                        
                        EigenschaftWert="{Binding Value}"
                        EigenschaftName="{Binding NameStringKey, Converter={StaticResource TranslateConverter}}"
                        HorizontalOptions="Center">                            
                        </xamlExt:CharacteristicEntry>
                </Border>
            </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

The Characteristic Object: (using using CommunityToolkit.Mvvm.ComponentModel;)

public partial class Characteristic : ObservableObject
    {

        [ObservableProperty]
        private string nameStringKey;

        [ObservableProperty]
        private string name;

        //public string Name => GetName();

        [ObservableProperty]
        private int value;

        public Characteristic() { }
        public Characteristic(string nameStringKey, int value) 
        {
            NameStringKey = nameStringKey;
            Value = value;            
        }
    }

The MainViewModel, where the Objects were initialised with the StringKey, later given to the Converter:

public partial class MainViewModel : ViewModelBase
    {
        [ObservableProperty]
        private ObservableCollection<Characteristic> characteristics;        

        public MainViewModel() 
        {                       
           Characteristics = new ObservableCollection<Characteristic> {
               new Characteristic("String49767",5),
               new Characteristic("String43013",5),
               new Characteristic("String91563",5),
               new Characteristic("String10423",5),
               new Characteristic("String63601",5),
               new Characteristic("String54738",5)};       

        }
    }

The Converter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{           
      return LocalizationResourceManager.Instance[value.ToString()].ToString();       
}   

The Command, where i change tha language via Button-Click in the AppShellViewModel:

[RelayCommand]
public async Task ChangeLanguage(object obj)
{  
   LocalizationResourceManager.Instance.SetCulture(new CultureInfo(obj.ToString()));
}

I really, really hope you can help me somehow, i am searching for a solution since 2 weeks, and don't get it run :( The UI simply does not update and i don't know why. Thank you very much.

VladislavAntonyuk commented 1 year ago

You need to pass BindingContext to MarkupExtension.

<Label Text="{localization:Translate NameStringKey, BindingContext={x:Reference MyPage}}" />

See solution in https://github.com/VladislavAntonyuk/MauiSamples/commit/485ea7ae0e47c4b5271f2b8f4f8a565967441fbf

The solution is ugly, but I haven't found a better way to calculate BindingValue.