Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary Operator in Xaml in Xamarin forms

I am working on Xamarin form apps. I wanted to to set Grdiview backgroud color based on condition of properties.

I know I can create a new property in class file and then bind to xaml but is there way to use ternary condition in Xaml itself.

my code is

<Grid Margin="5,0,5,5" Padding="10"  BackgroundColor="White">

This Grid being bind to model , which is having property IsRead ( null-able Boolean). Now I want to put condition that when IsRead is true then set Background color to Grey, otherwise White.

How can I do that within xaml?

like image 965
Mahajan344 Avatar asked Oct 17 '22 02:10

Mahajan344


2 Answers

I've never heard about such a thing, but you can use a converter instead. It's your best choice. It's clean, reusable and easy programmable.

Here is a well elaborated solution to this kind of need (surely you can do it in lots of ways, this one is just one).

Create a struct to make the solution completely reusable:

public struct NullableBoolColorScheme
{
    public Color TrueColor { get; set; }
    public Color FalseColor { get; set; }
    public Color NullColor { get; set; }

    public NullableBoolColorScheme(Color trueColor, Color falseColor, Color nullColor)
    {
        TrueColor = trueColor;
        FalseColor = falseColor;
        NullColor = nullColor;
    }

    public Color GetColor(bool? value)
    {
        if (!value.HasValue)
            return NullColor;
        else
            return value.Value ? TrueColor : FalseColor;
    }
}

Create your converter:

public class NullableBoolToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is bool?)) return null;

        Color returningColor = Color.Default;

        if (parameter != null && parameter is NullableBoolColorScheme)
            returningColor = ((NullableBoolColorScheme)parameter).GetColor((value as bool?));

        return returningColor;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new Exception("Conversion not allowed");
    }
}

Handle it in your ViewModel:

public class MyViewModel // Remember to implement INotifyPropertyChanged and raise property changes
{
    public bool? MyNullableBoolProperty
    {
        get;
        set; 
    }

    public NullableBoolColorScheme AppColorScheme { get; }

    public MyViewModel()
    {
        AppColorScheme = new NullableBoolColorScheme(Color.Gray, Color.White, Color.Transparent /* Some possibilities are open here =) */);
    }
}

Use it in XAML:

<!-- Declare your namespace -->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:converter="clr-namespace:Namespace.Converters"
         ...
         >
<!-- Create your resources dictionary and add a converter instance -->
    <ContentPage.Resources>
        <ResourceDictionary>
            <converter:NullableBoolToColorConverter x:Key="NullableBoolToColorConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <!-- Have fun -->
    <Grid Margin="5,0,5,5" 
          Padding="10"  
          BackgroundColor="{Binding MyNullableBoolProperty, Mode=OneWay, Converter={StaticResource NullableBoolToColorConverter}, ConverteParameter={Binding AppColorScheme}}">
        ...
    </Grid>
    ...
</ContentPage>

I hope it help you.

like image 85
Diego Rafael Souza Avatar answered Oct 21 '22 03:10

Diego Rafael Souza


You can not use Ternary in XAML.

Solution 1 (Using Converter):

You can probably go with using ValueConverter. Create a Converter which implements IValueConverter.

public class ReadUnReadToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
            bool? isRead = Convert.ToBoolean(value);
            if(isRead.HasValue && isRead.Value == true)
            {
                return Color.Grey;                    
            }    
            return Color.White;
    }

    //You may not need the Convert Back method. This will need to convert Color back to Boolean
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
         throw new NotImplementedException();
    }
}

In your XAML Resource, add this class as a static resource, then you can use this converter to bind value and convert based on this.

<ContentPage.Resources>      
   <local:ReadUnReadToColorConverter x:Key="ReadUnReadToColorConverter" />
</ContentPage.Resources>

Now, Bind this Converter to your Grid as follows:

<Grid Margin="5,0,5,5" Padding="10"  BackgroundColor="{Binding IsRead, Converter={StaticResource ReadUnReadToColorConverter}}">

Solution 2 (Using Property Binding (OneWay solution only)):

You can simply have a Color Property in your ViewModel and return value in the get method of the property based on the condition as follows:

public Color ReadUnReadBackgroundColor
{
    get
    {
        if(IsRead.HasValue && IsRead.Value == true)
        {
            return Color.Grey;                    
        }    
        return Color.White;            
    }
}

Now Bind this with Grid's BackgroundColor Property:

<Grid Margin="5,0,5,5" Padding="10"  BackgroundColor="{Binding ReadUnReadBackgroundColor}">
like image 40
MilanG Avatar answered Oct 21 '22 05:10

MilanG