简体   繁体   中英

Exposed Bindable Property not binding correctly

I'm having this problem with a custom view I made that connects a checkbox with a text and allows you to tap the entire view to tick the checkbox. But when I bind to the exposed binding from the checkbox It doesn't seem to react to changes. I'm clearly not understanding something and was hoping maybe someone here can see that obvious thing I am missing. A normal checkbox works just fine.

I looked at several of the solutions on site and tried a few of the things I found but alas, no dice.

xaml:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Celery.Controls.CheckboxWithTextControl">
    <ContentView.Content>
        <Grid ColumnDefinitions="*,48">
            <Grid.GestureRecognizers>
                <TapGestureRecognizer Tapped="OnTapped"/>
            </Grid.GestureRecognizers>
            <Label x:Name="DisplayedLabel"
                   HorizontalTextAlignment="Start"
                   VerticalTextAlignment="Center"/>
            <CheckBox x:Name="DisplayedCheckbox"
                      Grid.Column="1"
                      HorizontalOptions="Center"
                      VerticalOptions="Center">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroupList>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <VisualState.Setters>
                                    <Setter Property="Color" Value="{StaticResource TextColour}"/>
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="IsChecked">
                                <VisualState.Setters>
                                    <Setter Property="Color" Value="{StaticResource SecondryTextColor}"/>
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateGroupList>
                </VisualStateManager.VisualStateGroups>
            </CheckBox>
        </Grid>
    </ContentView.Content>
</ContentView>

cs

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Celery.Controls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CheckboxWithTextControl : ContentView
    {
        public static readonly BindableProperty TextProperty = 
            BindableProperty.Create("Text", typeof(string), typeof(CheckboxWithTextControl),"Default", BindingMode.OneWay, 
                propertyChanged: (bindable, oldValue, newValue) =>
                {
                    if (newValue != null && bindable is CheckboxWithTextControl control)
                    {
                        control.DisplayedLabel.Text = (string)newValue;
                    }
                });


        public static readonly BindableProperty IsCheckedProperty =
            BindableProperty.Create("IsChecked", typeof(bool), typeof(CheckboxWithTextControl),false , BindingMode.TwoWay,
                propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
                {
                    if (newValue != null && bindable is CheckboxWithTextControl control)
                    {
                        control.DisplayedCheckbox.IsChecked = (bool)newValue;
                    }
                });
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }

        public CheckboxWithTextControl()
        {
            InitializeComponent();
        }

        private void OnTapped(object sender, EventArgs e)
        {
            IsChecked = !IsChecked;
        }
    }
}

EDIT 1: I found out that if I tap the checkbox itself it breaks, but tapping anyother part of the screen works.

I changed the checkbox to also update the exposed bindable when it updates as such

private void OnCheckedChange(object sender, CheckedChangedEventArgs e)
        {
            if (IsChecked != e.Value) IsChecked = e.Value;
        }

and the checkbox is now

<CheckBox x:Name="DisplayedCheckbox"
                      Grid.Column="1"
                      HorizontalOptions="Center"
                      VerticalOptions="Center"
                      CheckedChanged="OnCheckedChange">

But when I bind to the exposed binding from the checkbox It doesn't seem to react to changes.

I test you code, and there is one problem with Grid, please modify your code by following code:

 <ContentView.Content>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.GestureRecognizers>
            <TapGestureRecognizer Tapped="OnTapped" />
        </Grid.GestureRecognizers>
        <Label
            x:Name="DisplayedLabel"
            Grid.Column="0"
            HorizontalTextAlignment="End"
            VerticalTextAlignment="Center" />
        <CheckBox
            x:Name="DisplayedCheckbox"
            Grid.Column="1"
            HorizontalOptions="StartAndExpand"
            VerticalOptions="Center">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <VisualState.Setters>
                                <Setter Property="Color" Value="Gray" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="IsChecked">
                            <VisualState.Setters>
                                <Setter Property="Color" Value="Red" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </VisualStateManager.VisualStateGroups>
        </CheckBox>
    </Grid>
</ContentView.Content>

Then you use this custom control like this:

  <customcontrol:CheckboxWithTextControl IsChecked="{Binding property}" Text="text" />

Do you implement INotifyPropertyChanged to update property value?

 public partial class Page1 : ContentPage, INotifyPropertyChanged
{
   
    private bool _property;
    public bool property
    {
        get { return _property; }
        set
        {
            _property = value;
            RaisePropertyChanged("property");
        }
    }
    public Page1()
    {
        InitializeComponent();           
        property = true;
        this.BindingContext = this;
    }

  
    public event PropertyChangedEventHandler PropertyChanged;

    
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM