Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement TranslateBinding #16

Merged
merged 1 commit into from
Oct 10, 2023
Merged

Implement TranslateBinding #16

merged 1 commit into from
Oct 10, 2023

Conversation

stephenquan
Copy link
Contributor

@stephenquan stephenquan commented Sep 25, 2023

Implement TranslateBinding markup extension which is similar to Binding but with these enhancements:

Path - Same as Binding.Path
Converter - Same as Binding.Converter
ConverterParameter - Same as Binding.ConverterParameter
StringFormat - Same as Binding.StringFormat
Source - Same as Binding.Source
TranslateFormat - Use string resource to lookup the string format
TranslateOne - Use string resource to lookup the string format when bound value is one (1)
TranslateZero - Use string resource to lookup the string format when bound value is zero (0)
TranslateValue - Translate the bound value

@stephenquan
Copy link
Contributor Author

#15

@SirJohnK
Copy link
Owner

SirJohnK commented Sep 29, 2023

(@stephenquan) Stephen, I really like this! 👍 Great work! I really appreciate the effort! To understand and to add nullable reference types I played around with your code and came up with the following. What do you think!?

using System.Collections.ObjectModel;
using System.Globalization;

namespace LocalizationResourceManager.Maui;

[ContentProperty(nameof(Path))]
public class TranslateBindingExtension : IMarkupExtension<BindingBase>, IMultiValueConverter
{
    /// <inheritdoc/>
    public string Path { get; set; } = ".";

    /// <inheritdoc/>
    public BindingMode Mode { get; set; } = BindingMode.OneWay;

    /// <inheritdoc/>
    public string StringFormat { get; set; } = "{0}";

    /// <inheritdoc/>
    public IValueConverter? Converter { get; set; } = null;

    /// <inheritdoc/>
    public object? ConverterParameter { get; set; } = null;

    /// <inheritdoc/>
    public object? Source { get; set; } = null;

    /// <inheritdoc/>
    public bool TranslateValue { get; set; } = false;

    /// <inheritdoc/>
    public string? TranslateFormat { get; set; }

    /// <inheritdoc/>
    public string? TranslateOne { get; set; }

    /// <inheritdoc/>
    public string? TranslateZero { get; set; }

    /// <inheritdoc/>
    public object ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
    }

    BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceProvider)
    {
        return new MultiBinding()
        {
            StringFormat = StringFormat,
            Converter = this,
            Mode = Mode,
            Bindings = new Collection<BindingBase>
            {
                new Binding(Path, Mode, Converter, ConverterParameter, source: Source),
                new Binding(nameof(LocalizationResourceManager.CurrentCulture), BindingMode.OneWay, source:LocalizationResourceManager.Current)
            }
        };
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var value = values?.FirstOrDefault();
        if (value is null)
        {
            return string.Empty;
        }

        if (!string.IsNullOrWhiteSpace(TranslateZero) && IsZero(value))
        {
            return LocalizationResourceManager.Current[TranslateZero, value];
        }

        if (!string.IsNullOrWhiteSpace(TranslateOne) && IsOne(value))
        {
            return LocalizationResourceManager.Current[TranslateOne, value];
        }

        if (!string.IsNullOrWhiteSpace(TranslateFormat))
        {
            return LocalizationResourceManager.Current[TranslateFormat, value];
        }

        if (TranslateValue)
        {
            return LocalizationResourceManager.Current[$"{value}"];
        }

        return value;
    }

    private static bool IsZero(object value) => (value is int number && number == 0);

    private static bool IsOne(object value) => (value is int number && number == 1);

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Copy link
Owner

@SirJohnK SirJohnK left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 👍

@SirJohnK SirJohnK merged commit ad41f8a into SirJohnK:main Oct 10, 2023
@stephenquan
Copy link
Contributor Author

@SirJohnK thanks for merging and pushing it to NuGet. Also thanks for the various cleanups such as the nullable support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants