如何在 xamarin.forms 中 upper/lower 区分 xaml 中的 resx 绑定?
how to upper/lower case resx bindings in xaml in xamarin.forms?
在 xamarin localization topic and sample TodoLocalized 之后,我制作了我的应用程序多语言。我的问题是有时,我有时需要使用大写的单词,我不想在 resx 文件中创建另一个翻译作为同一个单词的大写版本。实现这一目标的最佳方法是什么?如果可能扩展此翻译扩展名?还是应该使用 IValueConvertor?如果是,如何将其绑定到 xaml
// You exclude the 'Extension' suffix when using in Xaml markup
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
readonly CultureInfo ci;
const string ResourceId = "myApp.Resx.AppRes";
public TranslateExtension()
{
if (Device.OS == TargetPlatform.iOS || Device.OS == TargetPlatform.Android)
{
ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
}
}
public string Text { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
return "";
ResourceManager resmgr = new ResourceManager(ResourceId
, typeof(TranslateExtension).GetTypeInfo().Assembly);
var translation = resmgr.GetString(Text, ci);
if (translation == null)
{
#if DEBUG
throw new ArgumentException(
String.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", Text, ResourceId, ci.Name),
"Text");
#else
translation = Text; // HACK: returns the key, which GETS DISPLAYED TO THE USER
#endif
}
return translation;
}
}
我的Xaml:
<Button Image="ic_add.png" Text="{resx:Translate AddNew}"
Command="{Binding AddNew}" HorizontalOptions="FillAndExpand"/>
我试过这样做,但我想 Binding 需要在 BindingContext 中定义一个 属性。因此它不起作用,但我如何为 resx 文件中定义的文本实现它。
Text="{Binding {resx:Translate AddNew}, Converter={StaticResource UpperCaseConverter}}"
您可以尝试这样的操作:
<Button Text="{Binding Converter={StaticResource UpperCaseConverter}, ConverterParameter={resx:Translate AddNew}}"/>
这样您应该能够在转换器中访问翻译后的字符串
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return parameter.ToString().ToUpper();
}
如果 ConverterParameter
不起作用,您可以使用密钥并在转换器中获取已翻译的资源。
hankide 的回答也是正确的,但我在这里找到了更好的解决方案。显然,在 IMarkupExtension inherited class 中定义的任何 public 属性 都可以绑定。参考 xamarin doc
中的样本
所以我只是用
扩展了我的 TranslationExtension class
public bool IsUpper { get; set; } = false;
并在我需要大写的地方绑定它。我希望这对任何正在寻找相同解决方案的人有所帮助。
<Button Image="ic_add.png" Text="{resx:Translate AddNew}"
Command="{Binding AddNew, IsUpper=true}" HorizontalOptions="FillAndExpand"/>
为了使其更具可定制性,您可以在 TranslationExtension 中添加一个 属性 StringCase,如下所示:
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
public string Text { get; set; }
public string StringCase { get; set; }
........
........
if (!string.IsNullOrEmpty(StringCase))
{
if (StringCase.ToUpper().Equals("UPPER"))
{
translation = translation.ToUpper();
}
else if (StringCase.ToUpper().Equals("LOWER"))
{
translation = translation.ToLower();
}
}
return translation;
}
}
要保持文本正常:
<Label Text="{resx:Translate AddNew}"/>
<Button Text="{resx:Translate AddNew}"/>
将其设为大写:
<Label Text="{resx:Translate AddNew, StringCase=Upper}"/>
<Button Text="{resx:Translate AddNew, StringCase=Upper}"/>
将其设为小写:
<Label Text="{resx:Translate AddNew, StringCase=Lower}"/>
<Button Text="{resx:Translate AddNew, StringCase=Lower}"/>
这样,如果你想转换成CamelCase,PascalCase,SnakeCase或KebabCase,你也可以添加条件(但是除了Uppercase或Lowercase之外你可能不会遇到需要转换的情况)。
在 xamarin localization topic and sample TodoLocalized 之后,我制作了我的应用程序多语言。我的问题是有时,我有时需要使用大写的单词,我不想在 resx 文件中创建另一个翻译作为同一个单词的大写版本。实现这一目标的最佳方法是什么?如果可能扩展此翻译扩展名?还是应该使用 IValueConvertor?如果是,如何将其绑定到 xaml
// You exclude the 'Extension' suffix when using in Xaml markup
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
readonly CultureInfo ci;
const string ResourceId = "myApp.Resx.AppRes";
public TranslateExtension()
{
if (Device.OS == TargetPlatform.iOS || Device.OS == TargetPlatform.Android)
{
ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
}
}
public string Text { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
return "";
ResourceManager resmgr = new ResourceManager(ResourceId
, typeof(TranslateExtension).GetTypeInfo().Assembly);
var translation = resmgr.GetString(Text, ci);
if (translation == null)
{
#if DEBUG
throw new ArgumentException(
String.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", Text, ResourceId, ci.Name),
"Text");
#else
translation = Text; // HACK: returns the key, which GETS DISPLAYED TO THE USER
#endif
}
return translation;
}
}
我的Xaml:
<Button Image="ic_add.png" Text="{resx:Translate AddNew}"
Command="{Binding AddNew}" HorizontalOptions="FillAndExpand"/>
我试过这样做,但我想 Binding 需要在 BindingContext 中定义一个 属性。因此它不起作用,但我如何为 resx 文件中定义的文本实现它。
Text="{Binding {resx:Translate AddNew}, Converter={StaticResource UpperCaseConverter}}"
您可以尝试这样的操作:
<Button Text="{Binding Converter={StaticResource UpperCaseConverter}, ConverterParameter={resx:Translate AddNew}}"/>
这样您应该能够在转换器中访问翻译后的字符串
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return parameter.ToString().ToUpper();
}
如果 ConverterParameter
不起作用,您可以使用密钥并在转换器中获取已翻译的资源。
hankide 的回答也是正确的,但我在这里找到了更好的解决方案。显然,在 IMarkupExtension inherited class 中定义的任何 public 属性 都可以绑定。参考 xamarin doc
中的样本所以我只是用
扩展了我的 TranslationExtension classpublic bool IsUpper { get; set; } = false;
并在我需要大写的地方绑定它。我希望这对任何正在寻找相同解决方案的人有所帮助。
<Button Image="ic_add.png" Text="{resx:Translate AddNew}"
Command="{Binding AddNew, IsUpper=true}" HorizontalOptions="FillAndExpand"/>
为了使其更具可定制性,您可以在 TranslationExtension 中添加一个 属性 StringCase,如下所示:
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
public string Text { get; set; }
public string StringCase { get; set; }
........
........
if (!string.IsNullOrEmpty(StringCase))
{
if (StringCase.ToUpper().Equals("UPPER"))
{
translation = translation.ToUpper();
}
else if (StringCase.ToUpper().Equals("LOWER"))
{
translation = translation.ToLower();
}
}
return translation;
}
}
要保持文本正常:
<Label Text="{resx:Translate AddNew}"/>
<Button Text="{resx:Translate AddNew}"/>
将其设为大写:
<Label Text="{resx:Translate AddNew, StringCase=Upper}"/>
<Button Text="{resx:Translate AddNew, StringCase=Upper}"/>
将其设为小写:
<Label Text="{resx:Translate AddNew, StringCase=Lower}"/>
<Button Text="{resx:Translate AddNew, StringCase=Lower}"/>
这样,如果你想转换成CamelCase,PascalCase,SnakeCase或KebabCase,你也可以添加条件(但是除了Uppercase或Lowercase之外你可能不会遇到需要转换的情况)。