Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Bindable Events / Custom Control

StewartBasterashStewartBasterash USMember ✭✭
edited June 7 in Xamarin.Forms

I have designed a ContentView custom control. I know how to create simple custom controls with Bindable Properties, but I am struggling with "events".

I have a simple control for "code" selection. I have to supply the user with options and they will select the "codes" that apply to that product. I have created a grid (for the purpose of "overlay". It is a single cell grid (one row, one column). In that cell I have place, first a Label, and then a Checkbox.

Can someone point me in the right direction. The documentation is a bit confusing, and the examples are far from complete, in terms of explanation...

<Grid HeightRequest="21" WidthRequest="21" Margin="4"> <Grid.RowDefinitions> <RowDefinition Height="21" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="21" /> </Grid.ColumnDefinitions> <Label x:Name="codelabel" Grid.Column="0" Text="1" HorizontalTextAlignment="Center" TextColor="Black" FontAttributes="Bold" ScaleX="0.9" ScaleY="0.9"/> <CheckBox x:Name="codebox" Grid.Column="0" BackgroundColor="Transparent" Margin="-5" ScaleX="1.2" ScaleY="1.2" /> </Grid>
The idea is to expose the Label, which I have done with a bindable property, and a tapgesture in order to affect the checkbox and assign the selected value.

` [XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CodeCheckBox : ContentView
{
public static readonly BindableProperty CodeValueProperty = BindableProperty.Create(
propertyName: "CodeValue",
returnType: typeof(string),
declaringType: typeof(CodeCheckBox),
defaultValue: "0",
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: CodeValuePropertyChanged);
public string CodeValue
{
get { return (string)GetValue(CodeValueProperty); }
set { SetValue(CodeValueProperty, value); }
}

    private static void CodeValuePropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = (CodeCheckBox)bindable;
        control.codelabel.Text = (string)newValue;
    }

    public static readonly BindableProperty CommandProperty = BindableProperty.Create(
                                                     propertyName: "Command",
                                                     returnType: typeof(object),
                                                     declaringType: typeof(CodeCheckBox),
                                                     defaultValue: "",
                                                     defaultBindingMode: BindingMode.TwoWay);
                                                     //propertyChanged: CommandPropertyChanged);
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(
                                                     propertyName: "CommandParameter",
                                                     returnType: typeof(object),
                                                     declaringType: typeof(CodeCheckBox),
                                                     defaultValue: "",
                                                     defaultBindingMode: BindingMode.TwoWay);
                                                    //propertyChanged: CommandParameterPropertyChanged);
    public object CommandParameter
    {
        get { return (object)GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public event EventHandler Clicked;

    public CodeCheckBox()
    {
        InitializeComponent();

        codelabel.SetBinding(Label.TextProperty, new Binding("CodeValue", source:this));


        this.GestureRecognizers.Add(new TapGestureRecognizer
        {
            Command = new Command(() =>
            {
                Clicked?.Invoke(this, EventArgs.Empty);
                if (Command != null)
                {
                    if (Command.CanExecute(CommandParameter))
                        Command.Execute(CommandParameter);
                }
            })
        }); 
    }
}

`

Best Answers

  • StewartBasterashStewartBasterash USMember ✭✭
    Accepted Answer

    Thank you for your quick response... I have solved my own problem. I managed to do this all with Triggers and the NEW custom checkbox works perfectly... thank you!

    I would post the code, but XAML does not come across well in the post...

  • StewartBasterashStewartBasterash USMember ✭✭
    Accepted Answer

    I am continuing to have trouble with the "clicked" event... I have attached the "codeCheckBox" source... This is a very simple control as you will see, but the clicked event does not occur every time. Can you provide some guidance? This is holding me back.

    The idea is to "dynamically" create a given number of these for the user. The codes are usually a Letter which designates meaning to the end user... However, I will need to have a bound list the user can view, I will need to identify which codes the user has checked! So i will be updating a visual list for the user [Selections: H, T]. I would like to have a checked or changed event so that I can keep the list synced to what is on screen...

    FlexLayout



    /FlexLayout

    Thank you in advance...

Answers

  • JuniorJiangJuniorJiang Member, Xamarin Team Xamurai
    edited June 12

    Hi @StewartBasterash ,generally we can add Command in Custome View as follow :

    public partial class MyControlExample : ContentView
    {
        // BindableProperty implementation
        public static readonly BindableProperty CommandProperty = 
            BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(MyControlExample), null);
    
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }
    
        // Helper method for invoking commands safely
        public static void Execute(ICommand command)
        {
            if (command == null) return;
            if (command.CanExecute(null))
            {
                command.Execute(null);
            }
        }
    
        public MyControlExample()
        {
            InitializeComponent();
        }
    
        // this is the command that gets bound by the control in the view
        // (ie. a Button, TapRecognizer, or MR.Gestures)
        public Command OnTap => new Command(() => Execute(Command));
    }
    

    And here you also can share an image to explain what have done . Then I will check that with shared code .

  • StewartBasterashStewartBasterash USMember ✭✭
    Accepted Answer

    Thank you for your quick response... I have solved my own problem. I managed to do this all with Triggers and the NEW custom checkbox works perfectly... thank you!

    I would post the code, but XAML does not come across well in the post...

  • StewartBasterashStewartBasterash USMember ✭✭
    Accepted Answer

    I am continuing to have trouble with the "clicked" event... I have attached the "codeCheckBox" source... This is a very simple control as you will see, but the clicked event does not occur every time. Can you provide some guidance? This is holding me back.

    The idea is to "dynamically" create a given number of these for the user. The codes are usually a Letter which designates meaning to the end user... However, I will need to have a bound list the user can view, I will need to identify which codes the user has checked! So i will be updating a visual list for the user [Selections: H, T]. I would like to have a checked or changed event so that I can keep the list synced to what is on screen...

    FlexLayout



    /FlexLayout

    Thank you in advance...

Sign In or Register to comment.