Is there a way I can see the binding errors in while developing Xamarin Forms apps? The Application Output tab shows nothing but the binding doesn't work. How can I debug bindings?
I'd like to suggest you to add EmptyConverter:
public class EmptyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
Then create instance of converter on your page:
<ContentPage.Resources>
<ResourceDictionary>
<converters:EmptyConverter x:Key="EmptyConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
Then add converter to label:
<Label Text="{Binding Text, Converter={StaticResource EmptyConverter}}"/>
Put breakpoints in Convert and ConvertBack methods and you'll be able to see all changes of binded values.
Hope this will help you.
You can try to use the Compiled Bindings:
https://learn.microsoft.com/xamarin/xamarin-forms/app-fundamentals/data-binding/compiled-bindings
You will have gain performance and precise error reporting
Related
I am using a DataGrid control in Avalonia and I want to apply styles to DataGridRow based on data binding to the view model backing a row. How can I do this?
I figure it will be based on classes, so I defined a style for an isRequired class:
<DataGrid Items="{Binding Players}">
<DataGrid.Styles>
<Style Selector="DataGridRow.isRequired">
<Setter Property="Background" Value="LightGreen" />
</Style>
</DataGrid.Styles>
</DataGrid>
But notice the class is supposedly going to be set on a DataGridRow, but how can I set that class on the row based on a bound Player view model?
In WPF I'd often reach for Triggers but I've started to employ more Converters lately.
<DataGrid.Styles>
<Style Selector="DataGridRow">
<Setter Property="Background" Value="{Binding Tag, Converter={StaticResource OrderRowBackgroundConverter}}" />
</Style>
</DataGrid.Styles>
public class OrderRowBackgroundConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value != null)
{
switch (value.ToString())
{
case "":
return new SolidColorBrush(Color.Parse("#FF8D8D"));
case "fulfilled":
return new SolidColorBrush(Color.Parse("#B8FFB8"));
}
}
return new SolidColorBrush(Color.Parse("#FF8D8D"));
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Label Grid.Row="0" Grid.Column="1"
Text="{Binding Date, Converter={StaticResource localTimeConverter}, StringFormat='{0:MMMM dd, yyyy}'}"
LineBreakMode="NoWrap"
FontSize="16"
Style="{DynamicResource FieldLabel}"/>
I have the above Xaml and the below Converter:
public class UtcToLocalDateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((DateTime)value).ToLocalTime();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
However the Converter is not being called when the page starts instead it gets called when navigating away from the page. I add a break point in the convert method and that's when the method is being called. This is confusing!?
Please can someone offer some help?
Whoops ! This was my bad.
I was adding the converter into the SelectedItemTemplate of the ListView instead of the ItemTemplate of the ListView. Thats why the converter never got called. All fixed now.
How can i send the current element of my Actors list to my converter? and as well i need pass a parameter with ConverterParameter
<ListView x:Name="Actors" ItemsSource="{Binding Actors}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
Source="" IsVisible="{Binding ., Converter={StaticResource ListConverter}, ConverterParameter={Binding ActorCurrent}}"}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
this Actor exist in my view movel, i need to pass as parameter
private Actor _actorCurrent;
public Actor ActorCurrent
{
get => _actorCurrent;
set
{
_actorCurrent = value;
RaisePropertyChanged(() => ActorCurrent);
}
}
i tried with dot, but dont work
IsVisible="{Binding . // in my Converter class i dont nothing
EDIT 1:
i have as well this
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// i want to value = will be {Binding .,
// and parameter = will be ActorCurrent
// then i want to compare value with parameter and return a bool
}
Or can i use triggers?
<DataTrigger TargetType="Image" Binding="{Binding Name}" Value="{Binding ActorCurrent.name}">
i want to value = will be {Binding .}
You can get the value in the Convert method, you have to know the type of your value first. You can add a breakpoint there to get the type of value:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//if the type of value is Actor:
Actor tempActor = value as Actor;
//if the type of value is string:
string tempStr = value as string
return "123";
}
and parameter = will be ActorCurrent
Actually, you can't set binding to ConverterParameter as ConverterParameter is not a BindableProperty.
There is a discussion about this problem in this thread and you may find some idea there.
How to set CultureInfo globally for all decimal values.
Take one decimal value like
15.00
we may use
DecimalValue.ToString("C", new CultureInfo("en-GB"))
so that it will convert for that culture and output is
€15.00
But the question is am I able to Set the culture info for all decimal values that are going to display in the project?
Your better approach is too declare a converter for Decimal values, and use it wherever you need to display the values.
First you write your converter:
public class DecimalConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "0";
decimal decimalValue = (decimal)value;
return decimalValue.ToString("C", new CultureInfo("en-GB"))
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
then, in your App.xaml.cs, inside ResourceDictionary you declare it to use it in your application
Now, in your pages, wherever you bind decimal values, you can use it like this:
<Label Text="{Binding YourDecimalValue, Converter={StaticResource DecimalConverter}}"/>
I am writing an app with Xamarin.Forms and MvvmCross. I am having an issue with my converter. In my Core project:
public class BoolInverseValueConverter : MvxValueConverter<bool, bool>
{
public bool Convert(bool value, Type targetType, CultureInfo culture, object parameter)
{
return !value;
}
}
In my Forms project:
namespace MyApp.Forms.NativeConverters
{
public class BoolInverseValueConverter : MvxNativeValueConverter<MyApp.Core.Converters.BoolInverseValueConverter>
{
}
}
In my xaml:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:MyApp.Forms.NativeConverters;assembly=MyApp.Forms"
x:Class="MyApp.Forms.App">
<Application.Resources>
<converters:BoolInverseValueConverter x:Key="BoolInverseValueConverter" />
</Application.Resources>
In my page:
<views:MvxContentPage x:TypeArguments="viewModels:LoginViewModel"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
xmlns:mvx="clr-namespace:MvvmCross.Forms.Bindings;assembly=MvvmCross.Forms"
xmlns:viewModels="clr-namespace:MyApp.Core.ViewModels;assembly=MyApp.Core"
xmlns:localviews="clr-namespace:MyApp.Forms.Views;assembly=MyApp.Forms"
xmlns:resx="clr-namespace:MyApp.Core.Resources;assembly=MyApp.Core"
x:Class="MyApp.Forms.Pages.LoginPage"
Title="Login">
<ContentPage.Content>
<localviews:UserLoginView DataContext="{Binding .}" IsVisible="{mvx:MvxBind MyBoolVariable, Converter={StaticResource BoolInverseValueConverter}}"/>
</ContentPage.Content>
</views:MvxContentPage>
When I run the UWP app I get the message:
Cannot assign property “Converter”: Property does not exist, or is not
assignable, or mismatching type between value and property
I think MvvmCross is not scanning the assembly where you have your converter, thus it cannot be found. Try registering the converter class assembly in your Setup:
protected override IEnumerable<Assembly> ValueConverterAssemblies
{
get
{
var toReturn = base.ValueConverterAssemblies.ToList();
toReturn.Add(typeof(BoolInverseValueConverter).Assembly);
return toReturn;
}
}
HIH
no idea about MvvmCross, but in your xaml file, between
<Application.Resources>
and
<converters:BoolInverseValueConverter ...>
did you add
<ResourceDictionary> ?
Your converter should be something like below
public class BoolInverseValueConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null || (value as bool?) == false)
return Visibility.Collapsed;
else
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (value == null || (value as bool?) == false)
return Visibility.Collapsed;
else
return Visibility.Visible;
}
I ended up making the converter without MvvmCross to have it working. Maybe it's a bug in the current version of MvvmCross (6.2.1).