0

I am trying to figure out a way to make checkbox appear on button click on a page.

It's invisible by default, because I've set checkBox.Visibility = Android.Views.ViewStates.Invisible; in my custom renderer.

I have a button in the page content and a checkbox in the template which resides in pages resources.

From my ViewModel I am able to invoke PropertyChanged in CheckBox control where I can see the old and new value correctly set.

But I need a way to set it on the ViewRenderer. I'm guessing that it needs to handle some kind of event similar to CheckedChanged.

ViewModel

CheckBox c = new CheckBox { IsCheckBoxVisible=true,IsVisible=true };
CheckBox control

public class CheckBox : View
{
    /// <summary>
    /// The checked state property.
    /// </summary>
    public static readonly BindableProperty CheckedProperty =
        BindableProperty.Create<CheckBox, bool>(
            p => p.Checked, false, BindingMode.TwoWay, propertyChanged: OnCheckedPropertyChanged);

    **public static readonly BindableProperty IsCheckBoxVisibleProperty =
    BindableProperty.Create<CheckBox, bool>(
        p => p.IsCheckBoxVisible, false, BindingMode.OneWay, propertyChanged: OnVisibilityPropertyChanged);**

    /// <summary>
    /// The checked text property.
    /// </summary>
    public static readonly BindableProperty CheckedTextProperty =
        BindableProperty.Create<CheckBox, string>(
            p => p.CheckedText, string.Empty, BindingMode.TwoWay);

    /// <summary>
    /// The unchecked text property.
    /// </summary>
    public static readonly BindableProperty UncheckedTextProperty =
        BindableProperty.Create<CheckBox, string>(
            p => p.UncheckedText, string.Empty);

    /// <summary>
    /// The default text property.
    /// </summary>
    public static readonly BindableProperty DefaultTextProperty =
        BindableProperty.Create<CheckBox, string>(
            p => p.Text, string.Empty);

    /// <summary>
    /// Identifies the TextColor bindable property.
    /// </summary>
    /// 
    /// <remarks/>
    public static readonly BindableProperty TextColorProperty =
        BindableProperty.Create<CheckBox, Color>(
            p => p.TextColor, Color.Default);

    /// <summary>
    /// The font size property
    /// </summary>
    public static readonly BindableProperty FontSizeProperty =
        BindableProperty.Create<CheckBox, double>(
            p => p.FontSize, -1);

    /// <summary>
    /// The font name property.
    /// </summary>
    public static readonly BindableProperty FontNameProperty =
        BindableProperty.Create<CheckBox, string>(
            p => p.FontName, string.Empty);


    /// <summary>
    /// The checked changed event.
    /// </summary>
    public event EventHandler<EventArgs<bool>> CheckedChanged;

    **public event EventHandler<EventArgs<bool>> VisibilityChanged;**

    /// <summary>
    /// Gets or sets a value indicating whether the control is checked.
    /// </summary>
    /// <value>The checked state.</value>
    public bool Checked
    {
        get
        {
            return this.GetValue<bool>(CheckedProperty);
        }

        set
        {
            if (this.Checked != value)
            {
                this.SetValue(CheckedProperty, value);
                this.CheckedChanged.Invoke(this, value);
            }
        }
    }



    **public bool IsCheckBoxVisible
    {
        get
        {
            return this.GetValue<bool>(IsCheckBoxVisibleProperty);
        }
        set
        {
            if (this.IsCheckBoxVisible != value)
            {
                this.SetValue(IsCheckBoxVisibleProperty, value);
                this.VisibilityChanged.Invoke(this, value);
                //OnPropertyChanged("IsCheckBoxVisible");
            }
        }
    }**

    /// <summary>
    /// Gets or sets a value indicating the checked text.
    /// </summary>
    /// <value>The checked state.</value>
    /// <remarks>
    /// Overwrites the default text property if set when checkbox is checked.
    /// </remarks>
    public string CheckedText
    {
        get
        {
            return this.GetValue<string>(CheckedTextProperty);
        }

        set
        {
            this.SetValue(CheckedTextProperty, value);
        }
    }

    /// <summary>
    /// Gets or sets a value indicating whether the control is checked.
    /// </summary>
    /// <value>The checked state.</value>
    /// <remarks>
    /// Overwrites the default text property if set when checkbox is checked.
    /// </remarks>
    public string UncheckedText
    {
        get
        {
            return this.GetValue<string>(UncheckedTextProperty);
        }

        set
        {
            this.SetValue(UncheckedTextProperty, value);
        }
    }

    /// <summary>
    /// Gets or sets the text.
    /// </summary>
    public string DefaultText
    {
        get
        {
            return this.GetValue<string>(DefaultTextProperty);
        }

        set
        {
            this.SetValue(DefaultTextProperty, value);
        }
    }

    /// <summary>
    /// Gets or sets the color of the text.
    /// </summary>
    /// <value>The color of the text.</value>
    public Color TextColor
    {
        get
        {
            return this.GetValue<Color>(TextColorProperty);
        }

        set
        {
            this.SetValue(TextColorProperty, value);
        }
    }

    /// <summary>
    /// Gets or sets the size of the font.
    /// </summary>
    /// <value>The size of the font.</value>
    public double FontSize
    {
        get
        {
            return (double)GetValue(FontSizeProperty);
        }
        set
        {
            SetValue(FontSizeProperty, value);
        }
    }

    /// <summary>
    /// Gets or sets the name of the font.
    /// </summary>
    /// <value>The name of the font.</value>
    public string FontName
    {
        get
        {
            return (string)GetValue(FontNameProperty);
        }
        set
        {
            SetValue(FontNameProperty, value);
        }
    }
    /// <summary>
    /// Gets the text.
    /// </summary>
    /// <value>The text.</value>
    public string Text
    {
        get
        {
            return this.Checked
                ? (string.IsNullOrEmpty(this.CheckedText) ? this.DefaultText : this.CheckedText)
                    : (string.IsNullOrEmpty(this.UncheckedText) ? this.DefaultText : this.UncheckedText);
        }
    }

    /// <summary>
    /// Called when [checked property changed].
    /// </summary>
    /// <param name="bindable">The bindable.</param>
    /// <param name="oldvalue">if set to <c>true</c> [oldvalue].</param>
    /// <param name="newvalue">if set to <c>true</c> [newvalue].</param>
    private static void OnCheckedPropertyChanged(BindableObject bindable, bool oldvalue, bool newvalue)
    {
        var checkBox = (CheckBox)bindable;
        checkBox.Checked = newvalue;
    }

    **private static void OnVisibilityPropertyChanged(BindableObject bindable, bool oldvalue, bool newvalue)
    {
        var checkBox = (CheckBox)bindable;
        checkBox.IsCheckBoxVisible = newvalue;
    }**

}

CheckBoxRenderer

protected override void OnElementChanged(ElementChangedEventArgs e)
{
    base.OnElementChanged(e);

    if (this.Control == null)
    {
        var checkBox = new Android.Widget.CheckBox(this.Context);
        checkBox.Visibility = Android.Views.ViewStates.Invisible;
        checkBox.CheckedChange += CheckBoxCheckedChange;
        defaultTextColor = checkBox.TextColors;
        this.SetNativeControl(checkBox);
    }
    Control.Text = e.NewElement.Text;
    Control.Checked = e.NewElement.Checked;
    UpdateTextColor();
    if (e.NewElement.FontSize > 0)
    {
        Control.TextSize = (float)e.NewElement.FontSize;
    }

    if (!string.IsNullOrEmpty(e.NewElement.FontName))
    {
        Control.Typeface = TrySetFont(e.NewElement.FontName);
    }
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    switch (e.PropertyName)
    {
        case "Checked":
            Control.Text = Element.Text;
            Control.Checked = Element.Checked;
            break;
        case "TextColor":
            UpdateTextColor();
            break;
        case "FontName":
            if (!string.IsNullOrEmpty(Element.FontName))
            {
                Control.Typeface = TrySetFont(Element.FontName);
            }
            break;
        case "FontSize":
            if (Element.FontSize > 0)
            {
                Control.TextSize = (float)Element.FontSize;
            }
            break;
        case "CheckedText":
        case "UncheckedText":
            Control.Text = Element.Text;
            break;
       ** case "IsCheckBoxVisible":
            if(Element.IsCheckBoxVisible==true)
            {
                Control.Visibility = Android.Views.ViewStates.Visible;
            }
            else 
            {
                Control.Visibility = Android.Views.ViewStates.Invisible;
            }
            break;**
        default:
            System.Diagnostics.Debug.WriteLine("Property change for {0} has not been implemented.", e.PropertyName);
            break;
    }
}
Sven-Michael Stübe
  • 14,560
  • 4
  • 52
  • 103

1 Answers1

1

So this should actually be really simple. right now you have IsCheckBoxVisibleProperty, and you can get rid of it all together. The Xamarin.Forms.View already has an IsVisible property, and each platform specific renderer (VisualElementRenderer) knows how to handle visibility.

Therefore you can do this without issue.

var checkbox = new Checkbox();
checkbox .SetBinding (Checkbox.IsVisibleProperty, "IsCheckboxVisible");

Or in your XAML

<controls:Checkbox IsVisible="{Binding IsCheckboxVisible}" />

Of course this assumes you have a ViewModel similar to.

public class MyViewModel : BaseViewModel 
{
        private bool _isCheckboxVisible;
        public bool IsCheckboxVisible
        {
            get { return _isCheckboxVisible; }
            set { SetField(ref _isCheckboxVisible, value); }
        }
}
Chase Florell
  • 46,378
  • 57
  • 186
  • 376