I have a text binding in my XAML as follows:
Text="{Binding Converter={StaticResource ColumnToCaption}, ConverterParameter=-1}"
It simply takes the column number and looks up what the caption should be for that column based on data I have stored in a collection. That has been working fine but after one of the last set of upgrades to Visual Studio / Xamarin forms, the XAML intelisense started generating the error "Invalid Property Value". I didn't think much of it because the app seemed to work. Then some weird things started happing in my app and I noticed in my error list, I have a 43 "Invalid Property Value" errors listed (basically one for every place I use the ConverterParameter).
I double checked the MS documentation to ensure nothing changed (this link https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/converters) and it still shows passing the value in as a number is OK. Here is the example from the MS documentation:
<Label Text="{Binding Red, Converter={StaticResource doubleToInt}, ConverterParameter=255,
StringFormat='Red = {0:X2}'}" />
I am simply trying to rule this out as the source of my problem but I cannot seem to find out how to get the error to go away. Any assistance would be appreciated.
OH here is the converter code just so you can see it:
public class ColumnToCaption : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string ls_ReturnValue = "";
try
{
if (System.Convert.ToInt32(parameter.ToString()) < 0)
{
if (App.gvm_AppSettings.AutoExpire)
{
ls_ReturnValue = AppResources.Time;
}
else
{
ls_ReturnValue = AppResources.CheckedIn;
}
}
else
{
ls_ReturnValue = App.gvm_AppSettings.FormFieldCaptionText(Int32.Parse(parameter.ToString()));
}
}
catch (Exception ex)
{
App.ProcessException(ex);
}
return ls_ReturnValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Could you not add a string resource?
...
<ContentPage.Resources>
<ResourceDictionary>
<converters:DoubleToInt x:Key="doubleToInt" />
<x:String x:Key="twoFiveFive">255</x:String>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
...
<Label Text="{Binding Red, Converter={StaticResource doubleToInt}, ConverterParameter={StaticResource twoFiveFive}}" .../>
...
</ContentPage.Content>
Related
I am using the BoolToObjectConverter from Xamarin Community Toolkit (XCT) in my XAML file. The TrueObject and FalseObject properties are set to translatable strings where I use the TranslateExtension from XCT:
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
...
<xct:BoolToObjectConverter x:Key="Converter" TrueObject="{xct:Translate YesAnswer}" FalseObject="{xct:Translate NoAnswer}" />
...
<Label Text="{Binding Foo, Converter={StaticResource Converter}}" />
I would have expected that the Label text would have been the translated yes or no answer.
Unfortunately the actual Label output is
Xamarin.Forms.Binding
The issue could be solved by not using a converter but instead using a DataTrigger to set the Label.Text depending on the value of Foo. However, this clutters the XAML code; I would like to stick to using the BoolToObjectConverter. What can I do to obtain the translated string output instead of just the Binding type?
EDIT
Alternatively, I could add x:TypeArguments="BindingBase" in the converter definition, since this is the return type of the TranslateExtension.ProvideValue method, but this does not make any difference to the output result.
The best solution I could come up with was to subclass XCT TranslateExtension and implement IMarkupExtension for a string return value. This way I could use the subclass to obtain translated strings in the converter.
Implementation
public class TranslateToStringExtension : Xamarin.CommunityToolkit.Extensions.TranslateExtension, IMarkupExtension<string>
{
public new string ProvideValue(IServiceProvider serviceProvider)
{
var binding = base.ProvideValue(serviceProvider) as Binding;
string path;
var value = string.IsNullOrEmpty(path = binding?.Path?.Trim('[', ']'))
? null
: LocalizationResourceManager.Current.GetValue(path);
return value;
}
}
Usage
<xct:BoolToObjectConverter
x:Key="Converter"
TrueObject="{local:TranslateToString YesAnswer}"
FalseObject="{local:TranslateToString NoAnswer}" />
In Xamarin.Forms I implemented the interface IValueConverter.
public class NiceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string valueAsString = value as string;
return valueAsString + "SP";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string valueAsString = value as string;
return valueAsString + "GP";
}
}
In the XML part I bind an Entry text, and specify I use that convertor:
<ContentPage.Resources>
<convertorsNS:NiceConverter x:Key="myAddDollarSignConverter"/>
</ContentPage.Resources>
<StackLayout>
<Entry x:Name="myTextEntry" Text="{Binding NiceString ,
Converter = {StaticResource NiceConverter }, Mode=TwoWay}"/>
I would expect that when ever I type one character in the entry, lets say 'A',
ConvertBack() would be called, so the string 'AGP' would be
sent to the source binded property,
but now this causes to a change in the Source
binded property, so Convert () would be called, so the
string 'AGPSP' would be sent to the Target,
but now this causes to a change in the Target,
so now ConvertBack() would be called again, so the string AGPSPGP would be sent to the source
but now this causes to a change in the Source...
...and this way I expect it to go on and on endlessly.
Of course I'm wrong. Can you please tell me where?
this way I expect it to go on and on endlessly.
The text would not display as expected , it will cause infinite loop , the application hangs at that time .
It seems that Xamarin Team has fixed the problem that infinite loop would happen if we use converter on Entry when create binding .
Check the following threads ,the issue did exist before .
https://forums.xamarin.com/discussion/92310/two-way-binding-with-a-converter-causing-an-infinite-loop
Entry value converter hangs converting and converting back again and again
Xamarin forms value converter causing infinite loop
How do I access a user-modified value that's embedded inside of a custom control?
I have a custom control:
<ContentView
x:Class="MyNamspce.LabelValuePair"
x:Name="ParentControl"
mc:Ignorable="d">
<ContentView.Content>
<StackLayout>
...
<Entry Text="{Binding Source={x:Reference ParentControl}, Path=ValueText}" />
</StackLayout>
</ContentView.Content>
</ContentView>
Here's how I use the custom control:
<local:LabelValuePair
...
ValueText="{Binding ., Converter={StaticResource PairTemplateToEntryConverter}}" />
Here's the backing data structure:
type LabelEntryPair2 () =
member val LabelFGColor = "" with get,set
member val Label = "" with get,set
member val EntryValue = "" with get,set
member val ValueFGColor = "" with get,set
I'm successful at loading values into the custom control.
However, I'm not able to retrieve the values after they are modified by the user.
Note:
The ValueText property's setter is triggered every time I edit the entry control value thru the user interface:
The value converter, PairTemplateToEntryConverter, never invokes the ConvertBack method after I edit the entry value.
public static BindableProperty ValueTextProperty = BindableProperty.Create(
propertyName: "ValueText",
returnType: typeof(string),
declaringType: typeof(LabelValuePair),
defaultValue: "",
defaultBindingMode: BindingMode.TwoWay);
public string ValueText
{
get { return (string)GetValue(ValueTextProperty); }
set { SetValue(ValueTextProperty, value); } // ** This is being triggered every time **
}
However, I'm unable to pickup these updates on the actual data structure (i.e. LabelEntryPair2)
In conclusion, How do I access a user-modified value that's embedded inside of a custom control?
The issue here was this:
ValueText="{Binding ., Converter={StaticResource PairTemplateToEntryConverter}}"
So ValueText is being bound to the entire list item object, and then a converter is being used to extract the string from a string property on the object.This is an unusual approach and I see no real reason for it. Instead, why not just bind directly to the property on the object?> E.g:
ValueText="{Binding EntryValue}"
Dears,
I am calling two web service in my xamarin forms project. From the first web service I am getting the root URL of an image and from the second I am getting the remaining url part. Only the second web service response is connected with the listview using ItemsSource property. My root url is d1kv7s9g8y3npv.cloudfront.net. Currently, I hardcoded the rooturl value in my code.
My Image code:
<Image
Source="{Binding remainingUrl , StringFormat='d1kv7s9g8y3npv.cloudfront.net{0:F0}'}"
HorizontalOptions="Start"
VerticalOptions="Start"
WidthRequest="50" />
So how can I add the root url to this image code without hardcoding?
Thanks in advance
There is a simple solution to your problem.Simply create a property which will combine the both parts of the URL:
// In your ViewModel
public string CombinedUrl => $"{firstPart}/{secondPart}";
// In your XAML
<Image
Source="{Binding CombinedUrl}"
HorizontalOptions="Start"
VerticalOptions="Start"
WidthRequest="50" />
Please pay attention to naming conventions, from your example I can see that you are using a lowercase name 'remainingUrl' for a property which violates the naming conventions.
Finally, solve the issue using the Ivalueconverter.
The mainurl is stored in a variable using Application.Current.Properties.
The second web service is a list of items. So I need to join the two url and show it in the UI. For this, I am using IValueConverter.
My converter code:
public class UrlsLinkconverter : IValueConverter
{
#region IValueConverter implementation
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return string.Empty;
string rootUrl = Application.Current.Properties["rootUrl"].ToString();
string fullUrl = String.Concat("http://" + rootUrl,value.ToString())
Debug.WriteLine("fullUrl::>>>>"+fullUrl);
return fullUrl.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
Xamarin.Forms and Prism 6.3.0
It seems that I'm unable to get the ItemTappedEventArgs (or the sender object which is the ListView) by using the EventToCommandBehavior.
In my XAML, I have the 2 namespace defined
xmlns:b="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
xmlns:c="clr-namespace:Prism.Converters;assembly=Prism.Forms"
also in my XAML, in my ListView I have the following
<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemTapped" Command="{Binding ItemTappedCommand}"
EventArgsConverter="{StaticResource ItemTappedEventArgsConverter}"/>
</ListView.Behaviors>
In my ViewModel I declare my DelegateCommand
public DelegateCommand<object> ItemTappedCommand { get; set; }
I assign the command in the constructor of the ViewModel
ItemTappedCommand = new DelegateCommand<object>(ItemTapped);
and then I implement the command
void ItemTapped(object args)
{
...
}
I also have defined elsewhere in the code "MyApp/Converters" the ItemTappedEventArgsConverter that is proposed in the documentation.
The application (Android) show the usual "Application stopped working" message, before even start.
I was able to use the CommandParameter="MyParameter" instead of the EventArgsConverter in XAML and also I was able to get info from the item by using the EventArgsParameterPath="Item"
But the moment that I use the EventArgsConverter, I get the error and the application doesn't start.
What I'm doing wrong? How to get the args (or the sender) in the event behavior? Is there an example that I can use?
I figured out what was the problem. Actually there were 2 problems.
The first is the reference of the assembly that contains the converter.
Instead of
xmlns:c="clr-namespace:Prism.Converters;assembly=Prism.Forms"
it should be
xmlns:local="clr-namespace:MyApplication.Converters"
(or whatever is the name of the assembly that contains the converter)
The second mistake is that I didn’t have the following XAML in my content page
<ContentPage.Resources>
<ResourceDictionary>
<local:ItemTappedEventArgsConverter x:Key="ItemTappedEventArgsConverter" />
</ResourceDictionary>
</ContentPage.Resources>