Piotrek
Piotrek

Reputation: 11211

Passing event to XAML object using binding

Goal:

I want to run some method from ContentPage (class that manages XAML) inside ExtendableButtonList (custom View).

Problem:

ActionHandler - which represents event to call in ExtendableButtonList - always equals null. Every other property, configured the same way works, instead of this.

Is it even possible to pass a method using binding?

I'm sure that I'm not passing null value to my object.

XAML:

<ListView x:Name="emView">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <StackLayout Padding="20">
            <StackLayout BackgroundColor="Silver" Padding="20">
              [...]
              <customControls:ExtendableButtonList ActionHandler="{Binding ActionHandler}"></customControls:ExtendableButtonList>
            </StackLayout>
          </StackLayout>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>

ExtendableButtonList:

public class ExtendableButtonList : StackLayout
{
    public static readonly BindableProperty ActionHandlerProperty = BindableProperty.Create(
      propertyName: "ActionHandler",
      returnType: typeof(OneOfButtonClickedHandler),
      declaringType: typeof(ExtendableButtonList),
      defaultValue: default(OneOfButtonClickedHandler));

    public OneOfButtonClickedHandler ActionHandler
    {
        get { return (OneOfButtonClickedHandler)GetValue(ActionHandlerProperty); }
        set { SetValue(ActionHandlerProperty, value); }
    }

    public delegate void OneOfButtonClickedHandler(int buttonId, int action);
    public event OneOfButtonClickedHandler OneOfButtonsClicked;

    public ExtendableButtonList()
    {
        [...]


        PropertyChanged += CheckIfPropertyLoaded;
    }

    void CheckIfPropertyLoaded(object sender, PropertyChangedEventArgs e)
    {
        //wait until property ActionHandler will be loaded
        if(e.PropertyName == "ActionHandler")
        {
            OneOfButtonsClicked += ActionHandler;
        }
    }

    [...]
    void CalculationsFinished(){
        [...]
        OneOfButtonsClicked(buttonId, action);
    }

}

Upvotes: 1

Views: 1582

Answers (1)

Bonelol
Bonelol

Reputation: 546

Here is how they (XF) do,

public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(Button), null, propertyChanged: (bo, o, n) => ((Button)bo).OnCommandChanged());

public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(Button), null,
            propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).CommandCanExecuteChanged(bindable, EventArgs.Empty));

public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

public event EventHandler Clicked;
void IButtonController.SendClicked()
        {
            ICommand cmd = Command;
            if (cmd != null)
                cmd.Execute(CommandParameter);

            EventHandler handler = Clicked;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

copyed from https://github.com/xamarin/Xamarin.Forms/blob/2d9288eee6e6f197364a64308183725e7bd561f9/Xamarin.Forms.Core/Button.cs

And in your viewmodel or whatever, create an ICommand property and bind it to Command.

Upvotes: 2

Related Questions