0
votes

I have created a custom control that i want to change color after a click. I can successfully load it, but once I run my function and want to change the color, nothing happens. When i try to do it with a regular element (button, label) it works.

Custom control (that is a Grid with a simple label inside):

public partial class CustomGrid : Grid
{
    public static readonly BindableProperty ItemProperty = BindableProperty.Create(nameof(Item), typeof(Item), typeof(CustomGrid), propertyChanged: ItemChanged);
    public static readonly BindableProperty CustomColorProperty = BindableProperty.Create(nameof(IsAnonymousSubColor), typeof(Color), typeof(CustomGrid), propertyChanged: CustomColorChanged);

    public Color CustomColor
    {
        get { return (Color)GetValue(CustomColorProperty); }
        set { SetValue(CustomColorProperty, value); }
    }

    static void CustomColorChanged (object bindable, object oldValue, object newValue)
    {
        var x = bindable as CustomGrid;

        if (x.Item != null)
        {
             x.myLabelInMyXaml.BackgroundColor = x.CustomColor;
        }
    }

    static void ItemChanged (object bindable, object oldValue, object newValue)
    {
        var x = bindable as CustomGrid;
    }

    public Item Item
    {
        get { return (Item) GetValue(ItemProperty); }
        set { SetValue(ItemProperty, value); }
    }

    public CustomGrid()
    {
        InitializeComponent();
    }
}

Here is my xaml, here i bind it to the viewmodel color code (binding works well on other elements, even if i try it inside the same stacklayout).

                <StackLayout BackgroundColor="Transparent"
                             Padding="0,10,0,0"
                                 VerticalOptions = "StartAndExpand" 
                                BindableLayout.ItemsSource="{Binding newsService.FeedList}">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <StackLayout>

                                <controls:CustomGrid Item ="{Binding .}"
                                               CustomColor = "{Binding BindingContext.CustomColorViewModel, Source={x:Reference ParentView}}" />

                            </StackLayout>
                        </DataTemplate>
                    </BindableLayout.ItemTemplate>
                </StackLayout>

ViewModel:

    private Color _CustomColorViewModel;
    public Color CustomColorViewModel
    {
        get { return _CustomColorViewModel; }
        set
        {
            _CustomColorViewModel = value;
            RaisePropertyChanged("CustomColorViewModel");
        }
    }

And i change it after loading it:

public void ChangeColor ()
{
    CustomColorViewModel = Color.Red;
}

XAML of custom control:

  <?xml version="1.0" encoding="UTF-8"?>
  <Grid xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:controls="clr-namespace:Neutral.Controls"
         xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
         xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
         xmlns:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
         x:Name="ParentView"
         x:Class="Project.Controls.CustomGrid">


         <Label x:Name = "myLabelInMyXaml" BackgroundColor = "{Binding CustomColorViewModel}"/>


 </Grid>

But the custom control background color does not change. It works when i initially load, but not when i try to update it. Note that i have no issue with other elements, only this custom control.

Not sure why it does not update the color.

3
Can you post XAML of CustomGrid , most probably you have to do x.BackgroundColor=newColor in CustomColorChanged and you dont need x:Refernce ParentviewMorse
updated with xaml code as well.DiddanDo

3 Answers

2
votes

I notice you used CustomColor property in stacklayout, but you add the IsAnonymousSubColor property in your CustomColor background code.

I change your CustomColor background code like following format(Just test function to change the color).

  [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CustomGrid : Grid
    {

        public static readonly BindableProperty CustomColorProperty = BindableProperty.Create(nameof(CustomColor), typeof(Color), typeof(CustomGrid), propertyChanged: CustomColorChanged);

        public Color CustomColor
        {
            get { return (Color)GetValue(CustomColorProperty); }
            set { SetValue(CustomColorProperty, value); }
        }

        static void CustomColorChanged(object bindable, object oldValue, object newValue)
        {
            var x = bindable as CustomGrid;
            x.myLabelInMyXaml.BackgroundColor = x.CustomColor;

        }



        public CustomGrid()
        {
            InitializeComponent();
        }
    }

Here is running GIF.

enter image description here

0
votes

This is where the issue is:

x.myLabelInMyXaml.BackgroundColor = x.CustomColor;

Change it to:

x.myLabelInMyXaml.BackgroundColor = (Color) newValue;
0
votes

I think you may have an issue with the binding context.

Hard to say without seeing all of the code in context.

First of all, why are you calling a property a view model? The name doesn't really matter, but it is confusing as a property is not a view model, and without seeing the class that that property is in, it is hard to say what is going on here.

My suspicion is that the issue is here:

<controls:CustomGrid Item ="{Binding .}"
                     CustomColor = "{Binding BindingContext.CustomColorViewModel, Source={x:Reference ParentView}}" />

I think your binding code for the CustomColor should instead be (assuming your parent view is really named ParentView):

CustomColor = "{Binding Source={x:Reference ParentView}, Path=BindingContext.CustomColorViewModel}"

But again that is based on missing some vital code/information, but hopefully will at least move you in the right direction, if not be the solution.