-
Notifications
You must be signed in to change notification settings - Fork 1
Event bindings syntax
Note: Starting from v1.3.0 you can add '?' symbole at the begining of your binding text to enable design time check of your syntax.
When you want to create a binding between an event and a method call, you use a syntax like this:
<Button tools:Events.Bindings="Accept"/>
<!-- This will call the method Accept in the DataContext of the button (with out parameters)
when the Click event (default event of Button) is raised -->
The string assigned to the attached property Bindings
may be as simple as just a method call like in the previous example, or might be a complicated one containing the event name, method source path, parameter (type and object) with the use of element names and resources keys like:
<TextBox tools:Events.Bindings="GotFocus=$root.DataContext.ClearValue(person context)"/>
<!-- When the text box got focus, it will call method ClearValue (Which takes parameter of type person)
from the data context of UI element named 'root'
and pass the data context of this text box as parameter to that method -->
The previous example can be translated into the following complex C# code:
private void TextBox_GotFocus(object sender, EventArgs e)
{
((sender as TextBox).FindName("root").DataContext as YourViewModel).ClearValue((sender as TextBox).DataContext as Person);
}
Starting from version 1.1.0 you can bind event to command also in the very same way you do with methods:
<TextBox tools:Events.Bindings="GotFocus=ClearValueCommand(context)"/>
<!-- When the text box got focus, it will call Execute method of command ClearValueCommand
from the data context of UI element named 'root' and pass the data context of this text box
as parameter to that method -->
Please note that CanExecute
method from the command will be called first and if it returned true, the method Execute
will be called, otherwise no more calles will be made.
The previous example can be translated into the following complex C# code:
private void TextBox_GotFocus(object sender, EventArgs e)
{
var textBox = sender as TextBox;
var command = (textBox.DataContext as YourViewModel).ClearValueCommand;
if(command.CanExecute(textbox.DataContext)) command.Execute(textBox.DataContext);
}
You can also bind multiple events by separating their text with ,
like:
<TextBox tools.Events.Bindings="GotFocus=ClearValue,LostFocus=ValidateEmail($this.Text)"/>
However, the general syntax of event to method binding is:
<Button tools:Events.Bindings="[?][event=][methodSourcePath.]methodName[([parameterType] parameterPath)]"/>
-
?: (optional, starting from v1.3.0) If you started you event binding text with symbol
?
the designer will check that validity of your text at design time and show you any possible errors. However, you need to set the data context at design time (or use Design-Time Data-Preview feature). -
event: (optional) The event that will be used to call underlaying method. if you did not specify the event, the binding will search for the default event using attribute
DefaultEvent
on the object which to used the attached property on (Button in our example of syntax). - methodSourcePath: (optional) The object that contains the underlaying method. If you did not specify, the binding will use the data context (binding context in Xamarin Forms) of the object which to used the attached property on (Button in our example of syntax). However, this path follow the syntax of what we called Object Path and it will be explained later in this page.
-
MethodName: (required) The name of the method to be called. This is the only required part of the syntax!! This also can be a name to property of commands (implement ICommand interface), in this case, the
CanExecute
method will be called first, and if it returnedtrue
, the methodExecute
will be called, otherwise nothing will happen. -
ParameterType (optional) The type of parameter that underlaying method use. the binding will use this type to find the right overload of the method that accept parameter of that type (or assignable from), however id it did not find it will search for an overload that takes parameter of type
Object
, and if it did not find one it will through an exception. If you did not specify the parameter type, the binding will useObject
as parameter type. This part is ignored if MethodName points to a command property, Because ICommand has only one version ofExecute
andCanExecute
methods which takes parameter of typeobject
. - ParameterPath (optional) The object that will be passed to the underlaying method as parameter. If you did not specify, the binding will use an overload of the method that takes no parameters, and if could not find it, it will through an exception. However, this path follow the syntax of what we called Object Path and it will be explained later in this page.
Both method source object and parameter use what we call 'Object Path' which could be:
- Empty string: in this case the method source will be data context and the parameter will be ignored (parameterless method):
<Button tools:Events.Bindings="Accept"/>
<!-- When click is raised this will call `Accept` method in the data context of Button. -->
-
UI element: Starts with
$
followed by element name. You can also use properties in same way of your code like:
<Button tools:Events.Bindings="$root.DataContext.UpdateName($txtName.Text)"/>
<!-- When click is raised, this will call the method UpdateName in the data context of UI element named 'root',
and passes the text property of UI element named 'txtName' as parameter. -->
However, starting from version 1.2.0 you can safely delete the DataContext property after element name, because if it did not find the property or method in the element it will search the underlaying data context object for that member, and by that we can simplify the previous example to be like this:
<Button tools:Events.Bindings="$root.UpdateName($txtName.Text)"/>
<!-- When click is raised, this will call the method UpdateName in the data context of UI element named 'root',
and passes the text property of UI element named 'txtName' as parameter. -->
Just be careful if you data context and element object has the same member name, in this case if you try to access this member you will get it from the element not the data context.
-
UI resource: Starts with
#
followed by resource key. You can also use properties in same way of your code like:
<Button tools:Events.Bindings="#PersonsList.SelectedPerson.Delete"/>
<!-- When click is raised, this will call the method Delete (takes no parameter) in the
SelectedPerson property of UI resource named 'PersonsList'. -->
-
Keywords: Starts with
@
. Currently we have the following keywords:
- @this: Will use the object that you used the attached property:
<TextBox tools:Events.Bindings="LostFocus=ValidateName(@this.Text)"/>
<!-- When text box lost focus, it will call the method ValidateName of the data context and pass the
value of Text property of this text box. -->
- @context or @datacontext or @bindingcontext: Will use the data context of the object that you used the attached property:
<TextBox tools:Events.Bindings="LostFocus=ValidateName(@context.Person)"/>
<!-- When text box lost focus, it will call the method ValidateName of the data context and pass the
value of Person property of this text box data context. -->
- @sender: Will use the sender argument of the event:
<TextBox tools:Events.Bindings="LostFocus=ValidateName(@sender.Text)"/>
<!-- When text box lost focus, it will call the method ValidateName of the data context and pass the
value of Text property of the sender argument of the event handler. -->
- @args: Will use the EventArgs argument of the event:
<TextBox tools:Events.Bindings="LostFocus=ValidateName(@args)"/>
<!-- When text box lost focus, it will call the method ValidateName of the data context and pass the
EventArgs argument (e) of the event handler. -->
-
Auto detect: To get rid of the need to memorize all the previous signs
@ # $
, we introduced an auto detect sign!
. When you use it, the binder will search for a keyword after it, if it did not match it will search for an UI element with that name, and if it did not find a match, it will search for a resource with that key.