0

I have created a slider to know where is exactly is the point between 1-100, and now I want to change the color depending on the range, 0-50 green with a text "OK", 50-90 yellow with text "Careful", and above 90 red with text "Danger". But I can not even make it work with red color above 90.

MainPageViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;

namespace App1
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        private double slider;
        public double Slider
        {
            get => slider;
            set
            {
                slider = value;
                OnPropertyChanged(nameof(Slider).ToString());
                OnPropertyChanged(nameof(Color).ToString());
            }
        }
   
        public string Color()
        {
            if (Slider > 90)
            {
                return "Red";
            }
            else return "Black";
        }

        public ICommand ResetCommand { get; set; }

        public MainPageViewModel()
        {
            ResetCommand = new Command(Reset);
        }

        private void Reset()
        {
            Slider = double.MinValue;
        }
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }


        public event PropertyChangedEventHandler PropertyChanged;
    }
}

and this is my

MainPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App1.MainPage">

    <StackLayout>
        <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
            <Label HorizontalTextAlignment="Center" 
                   Text="Title"
                   TextColor="White" 
                   FontSize="36"/>
        </Frame>
        <Label HorizontalTextAlignment="Center" 
                   Text="{Binding Slider}"
                   TextColor="{Binding Color}" 
                   FontSize="36"/>
        <Slider VerticalOptions="FillAndExpand"
                Value="{Binding Slider}"
                Maximum="100" />
        <Button Text="Reset" Command="{Binding ResetCommand}"></Button>
    </StackLayout>

</ContentPage>

Trying with Properties:

public Color mycolor;
public Color MyColor
{
    get => mycolor;
    set
    {
        mycolor = value;
        {
            if (Slider > 90)
            {
                OnColorChanged(Color.Red);
            }
            else OnColorChanged(Color.Yellow);
        }

    }
}

and

private void OnColorChanged(Color propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName.ToString()));
}
Feber Castellon
  • 509
  • 1
  • 7
  • 21

3 Answers3

1

Color needs to be a public property that returns a Color, not a string.

    private double slider;
    public double Slider
    {
        get => slider;
        set
        {
            slider = value;
            OnPropertyChanged(nameof(Slider).ToString());
            OnPropertyChanged(nameof(Color).ToString());
        }
    }

    public Color Color
    {
        get {
          if (Slider > 90)
          {
            return Color.Red;
          }
          else return Color.Black;
        }
    }
Jason
  • 86,222
  • 15
  • 131
  • 146
  • Thank you very much, I changed that, but I committed 1 mistake that now I see. I was making "Public Color Color { set...." instead of the "get" I should. Thank you again. – Feber Castellon Oct 07 '20 at 17:52
0

Always use Converter for such cases.

Step 1 - ViewModel :

private int slider = 10;
public int Slider { get => slider; set { slider = value; OnPropertyChanged("Slider"); } }

Step 2 - Converter :

public class SliderValueToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // int is if you bind via property
            if (value is int sliderVal)
            {
                if (sliderVal < 50)
                    return Color.Green;
                else if (sliderVal >= 50 && sliderVal < 90)
                    return Color.Yellow;
                else
                    return Color.Red;
            }
            // double is you bind via x:reference
            else if (value is double sliderVal2)
            {
                if (sliderVal2 < 50)
                    return Color.Green;
                else if (sliderVal2 >= 50 && sliderVal2 < 90)
                    return Color.Yellow;
                else
                    return Color.Red;
            }
            return Color.Black;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }
}

Step 3 - View :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:DummyTestApp"
             mc:Ignorable="d" x:Name="BottomTabGridPageXaml"
             x:Class="DummyTestApp.BottomTabGridPage"
             BindingContext="{x:Reference BottomTabGridPageXaml}">
    <ContentPage.Resources>
        <local:SliderValueToColorConverter x:Key="SliderValueToColorConverter"/>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Margin="5" Padding="5" Spacing="5" VerticalOptions="CenterAndExpand">
            <Label HorizontalTextAlignment="Center" FontSize="36"
                   Text="{Binding Source={x:Reference mySlider},Path=Value}"
                   TextColor="{Binding Source={x:Reference mySlider},Path=Value,Converter={StaticResource SliderValueToColorConverter}}"/>
            <Slider x:Name="mySlider" VerticalOptions="FillAndExpand" Value="{Binding Slider}" Maximum="100" 
                    MinimumTrackColor="{Binding Slider,Converter={StaticResource SliderValueToColorConverter},Mode=TwoWay}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Shubham Tyagi
  • 798
  • 6
  • 21
-1

the expression TextColor="{Binding Color}" is like "i want to bind to a field called "Color". you need to specify an object or a class you bind to. this is the missing part of your code: a BindingContext. it is a pain to set it in xamarin. but if you do the true MVVM design as in example, it should work.

  • the issue is not binding else the label would not work , the property was bound to an incorrect object like binding IsVisible to string object. and the property was not raised . These were the two issues. – Shubham Tyagi Oct 08 '20 at 05:37