Thursday, 22 December 2016

Xamarin.Forms Behaviors: Revising InvokeMethodAction

Earlier in the year I blogged about using the EventHandlerBehavior, DataChangedBehavior, and InvokeMethodAction classes to invoke one or more methods when an event fires, or when data changes. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

A number of people have contacted me over the year about difficulties in getting the InvokeMethodAction class to invoke their methods. In all cases it was possible to invoke their methods – it just required more of an understanding about using the class. Therefore, in this blog post I’ll explore the InvokeMethodAction class in more depth.

Invoking a Method when an Event Fires

The EventHandlerBehavior class listens for a specified event to occur, and executes one or more actions in response. It requires you to set an EventName property to the event that you want the behavior to listen to, and an Actions property to one or more actions that should be executed in response to the event firing.

The InvokeMethodAction class executes a specified method when invoked. It requires you to set a TargetObject property to an object that exposes the method of interest, and a MethodName property to the name of the method to be invoked. The InvokeMethodAction class allows the following methods to be called:

  • A public method with zero parameters.
  • A public event handler method with two parameters.

Each scenario will now be explored.

Calling a Public Method without Parameters

The first scenario the InvokeMethodAction class targets is calling a public method with zero parameters, as demonstrated in the following code example:

<StackLayout.BindingContext> <local:InvokeMethodDemoPageViewModel /> </StackLayout.BindingContext> ... <Button Text="Invoke ViewModel Method"> <Button.Behaviors> <behaviors:EventHandlerBehavior EventName="Clicked"> <behaviors:InvokeMethodAction TargetObject="{Binding}" MethodName="IncrementCounter" /> </behaviors:EventHandlerBehavior> </Button.Behaviors> </Button>

The IncrementCounter method is public and doesn’t take any parameters:

public void IncrementCounter () { Counter++; OnPropertyChanged ("Counter"); }

When the Button.Clicked event fires, the IncrementCounter method is executed. The TargetObject property value specifies that the BindingContext exposes the method of interest. Therefore, the InvokeMethodAction class will search the BindingContext of the attached control for the method, which in this case is the InvokeMethodDemoPageViewModel instance.

Calling a Public Method with Two Parameters

The second scenario the InvokeMethodAction class targets it calling a public method with two parameters. This scenario is designed to handle invoking event handler methods.

Example 1

The following code shows an example of using the EventHandlerBehavior and InvokeMethodAction classes to invoke a Button.Clicked event handler method:

<StackLayout BindingContext="{x:Reference page}"> ... <Button Text="Invoke Page Method"> <Button.Behaviors> <behaviors:EventHandlerBehavior EventName="Clicked"> <behaviors:InvokeMethodAction TargetObject="{Binding}" MethodName="OnButtonClicked" /> </behaviors:EventHandlerBehavior> </Button.Behaviors> </Button> </StackLayout>

The OnButtonClicked method is public and takes two parameters:

public void OnButtonClicked (object sender, EventArgs args) { Counter++; }

Note that the OnButtonClicked method must accept parameters of the correct type for the Clicked event of a Button. Then, when the Button.Clicked event fires, the OnButtonClicked method is executed (which has a signature of object sender, EventArgs args). The TargetObject property value specifies that the BindingContext exposes the method of interest. Therefore, the InvokeMethodAction class will search the BindingContext of the attached control for the method, which in this case is the ContentPage. Note that the Actions property of the EventHandlerBehavior is set indirectly by creating the InvokeMethodAction instance as a child of the EventHandlerBehavior instance.

Example 2

The following code shows an example of using the EventHandlerBehavior and InvokeMethodAction classes to invoke a Label.PropertyChanged event handler method:

<ContentPage ... x:Name="page"> ... <Label Text="{Binding Message}"> <Label.Behaviors> <behaviors:EventHandlerBehavior EventName="PropertyChanged"> <behaviors:InvokeMethodAction TargetObject="{Binding Source={x:Reference page}}" MethodName="OnMessagePropertyChanged" /> </behaviors:EventHandlerBehavior> </Label.Behaviors> </Label> </ContentPage>

The OnMessagePropertyChanged method is public and takes two parameters:

public void OnMessagePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs args) { ... }
Note that the OnMessagePropertyChanged method must accept parameters of the correct type for the PropertyChanged event of a Label (technically the PropertyChanged event is defined in the BindableObject class, which the Label class ultimately inherits from). Then, when the Label.PropertyChanged event fires, the OnMessagePropertyChanged method is executed (which has a signature of object sender, PropertyChangedEventArgs args). The TargetObject property value specifies that the page class exposes the method of interest. Therefore, the InvokeMethodAction class will search the accompanying code-behind file for the OnMessagePropertyChanged method.

Invoking a Method when Data Changes

Previously, I’ve demonstrated using the DataChangedBehavior and InvokeMethodAction classes to invoke one or methods when data changes. Specifically, I demonstrated using the InvokeMethodAction class to invoke a public method with zero parameters.

The following code shows an example of using the DataChangedBehavior and InvokeMethodAction classes to invoke a method with two parameters:

<ContentPage ... x:Name="page"> ... <Label x:Name="doneLabel" Text="{Binding IsDone}"> <Label.Behaviors> <behaviors:DataChangedBehavior Binding="{Binding Source={x:Reference doneLabel}, Path=Text}" ComparisonCondition="Equal" Value="True"> <behaviors:InvokeMethodAction TargetObject="{Binding Source={x:Reference page}" MethodName="OnIsDoneChanged" /> </behaviors:DataChangedBehavior> </Label.Behaviors> </Label> </ContentPage>

The OnIsDoneChanged method is public and takes two parameters:

public void OnIsDoneChanged(object sender, string value) { ... }

Note that the OnIsDoneChanged method resembles an event handler, with the second parameter being of the type of the bound data (specified by the Binding property value of the DataChangedBehavior – in this case the string value of the bound Label.Text property). When the value of the Label.Text property becomes equal to “True”, the OnIsDoneChanged method is executed. The TargetObject property value specifies that the page class exposes the method of interest. Therefore, the InvokeMethodAction class will search the accompanying code-behind file for the OnIsDoneChanged method.

Summary

The InvokeMethodAction class executes a specified method in response to an event firing, or an item of data changing. Methods invoked by the class must be public and either have zero parameters, or two parameters. When methods have two parameters, their parameters must match the event being fired, or the type of the data that’s changed.

Friday, 1 July 2016

Xamarin.Forms Behaviors: RotateAction

Previously, I demonstrated using the EventHandlerBehavior and ScaleAction classes to run a scaling animation when an event occurs. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the EventHandlerBehavior and RotateAction classes to run a rotation animation when an event occurs.

Rotating a VisualElement when an Event Fires

The EventHandlerBehavior class listens for a specified event to occur, and executes one or more actions in response. It requires you to set an EventName property to the event that you want the behavior to listen to, and an Actions property to one or more actions that should be executed in response to the event firing. Note that the Actions property of the EventHandlerBehavior instance is set indirectly by creating the RotateAction instance as a child of the EventHandlerBehavior instance.

The RotateAction class performs a rotation animation, and allows the following optional properties to be set:

  • TargetObject – an object that is the VisualElement on which to run the animation. If this value is omitted the object the behavior is attached to will be set as the target on which to run the animation.
  • FinalAngle – a double that specifies the angle of the Rotation property to animate to. If this value is omitted the default value of 0.0 is used.
  • Axis – a RotationAxis that specifies whether to rotate on the X, Y, or Z axis. If this value is omitted the default value of Z is used.
  • Duration – an int that represents the length of the animation in milliseconds. If this value is omitted the default value of 250ms is used.
  • EasingFunction – an EasingFunction that specifies any velocity changes in the animation. If this value is omitted the default value of the Linear easing function is used.
  • IsRelative – a boolean that specifies whether to perform relative scaling. If this value is omitted the default value of false will be used. Relative rotation obtains the current Rotation property value for the start of the animation, and then rotates from that value to the value plus the value defined by the FinalAngle property.
  • Await – a boolean that represents whether the animation should be awaited, or whether it should be allowed to complete in the background. If this value is omitted the default value of false will be used.

The following code example demonstrates using the EventHandlerBehavior and RotateAction classes to implement a compound animation that concurrently rotates an Image control on the X, Y, and Z axes:

<Image x:Name="image" Source="monkey.png" Opacity="0" VerticalOptions="CenterAndExpand" /> <Button Text="Run Animation"> <Button.Behaviors> <behaviors:EventHandlerBehavior EventName="Clicked"> <!-- Compound Animation --> <behaviors:RotateAction TargetObject="{x:Reference image}" Duration="600000" FinalAngle="110520" /> <behaviors:RotateAction TargetObject="{x:Reference image}" Duration="600000" FinalAngle="90360" Axis="X" /> <behaviors:RotateAction TargetObject="{x:Reference image}" Duration="600000" FinalAngle="71640" Axis="Y" /> </behaviors:EventHandlerBehavior> </Button.Behaviors> </Button>

When the Button.Clicked event fires, three RotateAction instances are concurrently executed over 10 minutes (600000 milliseconds). Each RotateAction instance makes a different number of 360 degree rotations – 307 rotations on the Z axis (110520/360 = 307), 251 rotations on the X axis (90360/360 = 251), and 199 rotations on the Y axis (71640/360 = 199). These values are prime numbers, therefore ensuring that the rotations aren’t synchronized and hence won’t result in repetitive patterns.

The advantage of using the RotateAction is that it’s possible to invoke animations through XAML, rather than having to use C#. In addition, when combined with behaviors, a scaling animation can easily be invoked from XAML when a behavior occurs, such as an event firing, or when a piece of data changes.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The RotateAction class allows rotation animations to be invoked through XAML when a behaviors occurs, such as an event firing, or when a piece of data changes.

Thursday, 30 June 2016

Xamarin.Forms Behaviors: ScaleAction

Previously, I demonstrated using the EventHandlerBehavior and TranslateAction classes to run a translation animation when an event occurs. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the EventHandlerBehavior and ScaleAction classes to run a scaling animation when an event occurs.

Scaling a VisualElement when an Event Fires

The EventHandlerBehavior class listens for a specified event to occur, and executes one or more actions in response. It requires you to set an EventName property to the event that you want the behavior to listen to, and an Actions property to one or more actions that should be executed in response to the event firing. Note that the Actions property of the EventHandlerBehavior instance is set indirectly by creating the ScaleAction instance as a child of the EventHandlerBehavior instance.

The ScaleAction class performs a scaling animation, which expands or contracts a VisualElement when invoked, and allows the following optional properties to be set:

  • TargetObject – an object that is the VisualElement on which to run the animation. If this value is omitted the object the behavior is attached to will be set as the target on which to run the animation.
  • FinalScale – a double that specifies the value of the Scale property to animate to. If this value is omitted the default value of 1 is used.
  • Duration – an int that represents the length of the animation in milliseconds. If this value is omitted the default value of 250ms is used.
  • EasingFunction – an EasingFunction that specifies any velocity changes in the animation. If this value is omitted the default value of the Linear easing function is used.
  • IsRelative – a boolean that specifies whether to perform relative scaling. If this value is omitted the default value of false will be used. Relative scaling obtains the current Scale property value for the start of the animation, and then scales from that value to the value plus the value defined by the FinalScale property.
  • Await – a boolean that represents whether the animation should be awaited, or whether it should be allowed to complete in the background. If this value is omitted the default value of false will be used.

The following code example demonstrates using the EventHandlerBehavior and ScaleAction classes to implement a scaling animation that expands and contracts an Image control when a Button is clicked:

<Image x:Name="image" Source="monkey.png" Opacity="0" VerticalOptions="CenterAndExpand" /> <Button Text="Run Animation"> <Button.Behaviors> <behaviors:EventHandlerBehavior EventName="Clicked"> <behaviors:ScaleAction TargetObject="{x:Reference image}" FinalScale="2.0" Duration="3000" EasingFunction="SpringIn" Await="true"/> <behaviors:ScaleAction TargetObject="{x:Reference image}" FinalScale="1.0" Duration="3000" EasingFunction="SpringOut" /> </behaviors:EventHandlerBehavior> </Button.Behaviors> </Button>

When the Button.Clicked event fires, two ScaleAction instances execute over 6 seconds. The first ScaleAction instance expands the Image instance to twice its size over 3 seconds (3000 milliseconds), and uses the SpringIn easing function to cause the animation to accelerate towards the end. Once the first ScaleAction instance has executed the second ScaleAction instance begins. This is because the first ScaleAction instance sets the Await property to true. The second ScaleAction instances causes the Image to contract back to its original size over 3 seconds (3000 milliseconds), and uses the SpringOut easing function to cause the animation to decelerate towards the end.

The advantage of using the ScaleAction is that it’s possible to invoke animations through XAML, rather than having to use C#. In addition, when combined with behaviors, a scaling animation can easily be invoked from XAML when a behavior occurs, such as event firing, or when a piece of data changes.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The ScaleAction class allows scaling animations to be invoked through XAML when a behavior occurs, such as an event firing, or when a piece of data changes.

Monday, 20 June 2016

Xamarin.Forms Behaviors: TranslateAction

Previously, I demonstrated using the EventHandlerBehavior and FadeAction classes to run a fade animation when an event occurs. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the EventHandlerBehavior and TranslateAction classes to run a translation animation when an event occurs.

Translating a VisualElement when an Event Fires

The EventHandlerBehavior class listens for a specified event to occur, and executes one or more actions in response. It requires you to set an EventName property to the event that you want the behavior to listen to, and an Actions property to one or more actions that should be executed in response to the event firing. Note that the Actions property of the EventHandlerBehavior instance is set indirectly by creating the TranslateAction instance as a child of the EventHandlerBehavior instance.

The TranslateAction class performs a translation animation, which moves a VisualElement, when invoked, and allows the following optional properties to be set:

  • TargetObject – an object that is the VisualElement on which to run the animation. If this value is omitted the object the behavior is attached to will be set as the target on which to run the animation.
  • X – a double that specifies the number of pixels to move the TargetObject horizontally. If this value is omitted the default value of 1 is used.
  • Y – a double that specifies the number of pixels to move the TargetObject vertically. If this value is omitted the default value of 1 is used.
  • Duration – an int that represents the length of the animation in milliseconds. If this value is omitted the default value of 250ms is used.
  • EasingFunction – an EasingFunction that specifies any velocity changes in the animation. If this value is omitted the default value of the linear easing function is used.
  • Await – a boolean that represents whether the animation should be awaited, or whether it should be allowed to complete in the background. If this value is omitted the default value of false is used.

The following code example demonstrates using the EventHandlerBehavior and TranslateAction classes to implement a compound animation that moves an Image control around the screen when a Button is clicked:

<Image x:Name="image" Source="monkey.png" Opacity="0" VerticalOptions="CenterAndExpand" /> <Button Text="Run Animation"> <Button.Behaviors> <behaviors:EventHandlerBehavior EventName="Clicked"> <behaviors:TranslateAction TargetObject="{x:Reference image}" X="-100" Y="0" Duration="1000" Await="true" /> <behaviors:TranslateAction TargetObject="{x:Reference image}" X="-100" Y="-100" Duration="1000" Await="true" /> <behaviors:TranslateAction TargetObject="{x:Reference image}" X="100" Y="100" Duration="1000" Await="true" /> <behaviors:TranslateAction TargetObject="{x:Reference image}" X="0" Y="100" Duration="1000" Await="true" /> <behaviors:TranslateAction TargetObject="{x:Reference image}" X="0" Y="0" Duration="1000" Await="true" /> </behaviors:EventHandlerBehavior> </Button.Behaviors> </Button>

When the Button.Clicked event fires, a series of TranslateAction instances creates a compound animation, which is a sequential combination of animations. Specifically, an Image is translated around the screen over 5 seconds (5000 milliseconds). The translation of the Image uses five translation animations, with the Await property of each TranslateAction instance indicating that each animation executes sequentially. Therefore, subsequent animation methods execute after the previous method has completed,

The advantage of using the TranslateAction is that it’s possible to invoke animations through XAML, rather than having to use C#. In addition, when combined with behaviors, a translation animation can easily be invoked from XAML when a behavior occurs, such as an event firing, or a when a piece of data changes.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The TranslateAction class allows translation animations to be invoked through XAML when a behavior occurs, such as an event firing, or when a piece of data changes.

Friday, 10 June 2016

Xamarin.Forms Behaviors: FadeAction

Previously, I mentioned that I’d added a number of new actions to the Behaviors Library for Xamarin.Forms, to support animations. The library has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the EventHandlerBehavior and FadeAction classes to run a fade animation when an event occurs.

Fading a VisualElement when an Event Fires

The EventHandlerBehavior class listens for a specified event to occur, and executes one or more actions in response. It requires you to set an EventName property to the event that you want the behavior to listen to, and an Actions property to one or more actions that should be executed in response to the event firing. Note that the Actions property of the EventHandlerBehavior instance is set indirectly by creating the FadeAction instance as a child of the EventHandlerBehavior instance.

The FadeAction class performs a fade animation when invoked, and allows the following optional properties to be set:

  • TargetObject – an object that is the VisualElement on which to run the animation. If this value is omitted the object the behavior is attached to will be set as the target on which to run the animation.
  • FinalOpacity – a double that specifies the value of the Opacity property to fade to. If this value is omitted the default value of 1 is used.
  • Duration – an int that represents the length of the animation in milliseconds. If this value is omitted the default value of 250ms is used.
  • EasingFunction – an EasingFunction that specifies any velocity changes in the animation. If this value is omitted the default value of the linear easing function is used.
  • Await – a boolean that represents whether the animation should be awaited, or whether it should be allowed to complete in the background. If this value is omitted the default value of false is used.

The following code example shows an example of using the EventHandlerBehavior and FadeAction classes to fade in an Image control when a Button is clicked:

<Image x:Name="image" Source="monkey.png" Opacity="0" VerticalOptions="CenterAndExpand" /> <Button Text="Run Animation"> <Button.Behaviors> <behaviors:EventHandlerBehavior EventName="Clicked"> <behaviors:FadeAction TargetObject="{x:Reference image}" FinalOpacity="1.0" Duration="2000" Await="true" /> </behaviors:EventHandlerBehavior> </Button.Behaviors> </Button>

When the Button.Clicked event fires, the FadeAction fades in the Image instance over 2 seconds (2000 milliseconds), and the animation is awaited. This means that if there were subsequent animations defined, they would only execute after the fade animation has completed,

The advantage of using the FadeAction is that it’s possible to invoke animations through XAML, rather than having to use C#. In addition, when combined with behaviors, a fade animation can easily be invoked from XAML when a behavior occurs, such as an event firing, or a when a piece of data changes.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The FadeAction class allows fade animations to be invoked through XAML when a behavior occurs, such as an event firing, or when a piece of data changes.

Thursday, 26 May 2016

Xamarin.Forms Behaviors: New Actions

My Behaviors Library for Xamarin.Forms is a PCL I’ve created that can be consumed by Xamarin.Forms applications, and can be downloaded from GitHub and NuGet. The library has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

I’ve recently added a number of new actions to the library, to support animations. The actions are:

  • FadeAction
  • RotateAction
  • ScaleAction
  • TranslateAction

The advantage of using these actions is that it’s possible to invoke animation through XAML, rather than having to use C#. In addition, when combined with behaviors, compound animations can easily be invoked through XAML when a behavior occurs, such as an event firing, or a piece of data changing.

Stay tuned over the next few weeks for details of how to consume these actions.

Tuesday, 26 April 2016

Xamarin.Forms Behaviors: Support for Page Level Behaviors

Previously, I’ve introduced by Behaviors Library for Xamarin.Forms, which can be downloaded from GitHub and NuGet. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

A problem with my behaviors library was that it only allowed behaviors to be attached to views (controls), and not to pages. Therefore, I’ve updated the library so that behaviors can be attached to pages.

In this blog post, I’ll demonstrate using the EventHandlerBehavior and InvokeCommandAction classes to invoke a command when a page event fires.

Invoking a Command when a Page Event Fires

The EventHandlerBehavior class listens for a specified event to occur, and executes one or more actions in response. It requires you to set an EventName property to the event that you want the behavior to listen to, and an Actions property to one or more actions that should be executed in response to the event firing.

The InvokeCommandAction class executes a specified ICommand when invoked. It requires you to set a Command property to an ICommand instance, and CommandParameter and Converter properties can be optionally set. The CommandParameter property should be set to an object instance, with the Converter property being set to an instance of a class that implements IValueConverter. The ICommand specified in the Command property will then be executed, with the CommandParameter and Converter values being used if specified.

The following code shows an example of using the EventHandlerBehavior to invoke a command:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:behaviors="clr-namespace:Behaviors;assembly=Behaviors" x:Class="Behaviors.Sample.InvokeCommandDemoPage" Title="InvokeCommand Demo" Icon="xaml.png"> <ContentPage.BindingContext> <local:InvokeCommandDemoPageViewModel /> </ContentPage.BindingContext> ... <ContentPage.Behaviors> <behaviors:EventHandlerBehavior EventName="Appearing"> <behaviors:InvokeCommandAction Command="{Binding PageAppearingCommand}" /> </behaviors:EventHandlerBehavior> <behaviors:EventHandlerBehavior EventName="Disappearing"> <behaviors:InvokeCommandAction Command="{Binding PageDisappearingCommand}" /> </behaviors:EventHandlerBehavior> </ContentPage.Behaviors> ... </ContentPage>

When the Page.Appearing event fires, the PageAppearingCommand is executed. Similarly, when the Page.Disappearing event fires, the PageDisappearingCommand is executed. The InvokeCommandAction class expects to find the ICommand instances on the BindingContext of the attached object, and in this case the BindingContext is set to an instance of the InvokeCommandDemoPageViewModel class. Note that the Actions property of the EventHandlerBehavior instances is set indirectly by creating each InvokeCommandAction instance as a child of each EventHandlerBehavior instance. When the ICommand instances are executed, they display alerts that confirm that the appropriate page event fired.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The Behaviors Library for Xamarin.Forms now supports attaching behaviors at the page level. This enables actions to be executed in response to a page event firing.

Wednesday, 13 April 2016

Xamarin.Forms Behaviors Library: What’s next?

The Behaviors Library for Xamarin.Forms seems to have been well received, so I intend enhancing it as time allows. This includes:

  • Ensuring that behaviors can be added to pages. At the moment they can only be added to views.
  • Adding more useful behaviors. I have plenty of ideas here.

Questions? Problems? Thoughts? Suggestions? Then drop me a line.

Xamarin.Forms Behaviors: DataChangedBehavior and SetPropertyAction

Previously, I demonstrated using the DataChangedBehavior and InvokeMethodAction classes to invoke one or more methods when data changes. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the DataChangedBehavior and SetPropertyAction classes to set one or more properties when data changes.

Setting a Property when Data Changes

The DataChangedBehavior class listens for the bound data to meet a specified condition, and executes one or more actions in response. It requires you to set the following properties:

  • Binding – an object that represents the bound object that the behavior will listen to.
  • ComparisonCondition – a ComparisonCondition enumeration value that represents the comparison to be performed between the values of the Binding and Value properties. The enumeration values are: Equal, NotEqual, LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual.
  • Value – an object that represents the value to be compared with the value of the Binding property.
  • Actions – one or more actions that should be executed in response to the bound data changing. Note that this property is set indirectly.

The SetPropertyAction class sets a specified property when invoked. It requires you to set a TargetObject property to an object that exposes the property of interest, a PropertyName property to the name of the property to be set, and a Value property to an object that represents the property value to be set.

The following code example shows an example of using the DataChangedBehavior and SetPropertyAction classes to set the colour of BoxView control and a ViewModel property as a Slider value changes:

<ContentPage.BindingContext> <local:SetPropertyDemoPageViewModel /> </ContentPage.BindingContext> <Slider x:Name="slider" Minimum="0" Maximum="100"> <Slider.Behaviors> <behaviors:DataChangedBehavior Binding="{Binding Path=Value, Source={x:Reference slider}}" ComparisonCondition="LessThan" Value="1"> <behaviors:SetPropertyAction TargetObject="{x:Reference changingBoxView}" PropertyName="Color" Value="{StaticResource ColorAqua}" /> <behaviors:SetPropertyAction TargetObject="{Binding}" PropertyName="ColourText" Value="Aqua" /> </behaviors:DataChangedBehavior> <behaviors:DataChangedBehavior Binding="{Binding Path=Value, Source={x:Reference slider}}" ComparisonCondition="GreaterThanOrEqual" Value="1"> <behaviors:SetPropertyAction TargetObject="{x:Reference changingBoxView}" PropertyName="Color" Value="{StaticResource ColorRed}" /> <behaviors:SetPropertyAction TargetObject="{Binding}" PropertyName="ColourText" Value="Red" /> </behaviors:DataChangedBehavior> ... </Slider.Behaviors> </Slider> <BoxView x:Name="changingBoxView" WidthRequest="100" Color="Aqua" HeightRequest="100" ... /> <StackLayout Orientation="Horizontal" HorizontalOptions="Center"> <Label Text="Slider value:" /> <Label BindingContext="{x:Reference slider}" Text="{Binding Value, StringFormat='{0:F0}'}" /> </StackLayout> <StackLayout Orientation="Horizontal" HorizontalOptions="Center"> <Label Text="Colour:" /> <Label Text="{Binding ColourText}" /> </StackLayout>

When the Value property of the Slider changes a series of DataChangedBehavior instances are executed. Each behavior instance compares the Value property of the Slider against a value, and executes two SetPropertyAction instances if the comparison is true. The first SetPropertyAction instance changes the Color property value of the BoxView, while the second SetPropertyAction instance sets the ColourText property of the SetPropertyDemoViewModel instance. Note that the Actions property of each DataChangedBehavior instance is set indirectly by creating the SetPropertyAction instances as children of the DataChangedBehavior instances.

The advantage of combining the DataChangedBehavior and SetPropertyAction classes is that properties of controls and ViewModels can easily be set when data changes, therefore removing boiler-plate property setting code from code-behind and ViewModels.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The DataChangedBehavior class listens for the bound data to meet a specified condition, and executes one or more actions in response. The SetPropertyAction class sets a specified property when invoked. The advantage of combining the DataChangedBehavior and SetPropertyAction classes is that properties of controls and ViewModels can easily be set when data changes, therefore removing boiler-plate property setting code from code-behind and ViewModels.

Monday, 4 April 2016

Xamarin.Forms Behaviors: DataChangedBehavior and InvokeMethodAction

Previously, I demonstrated using the DataChangedBehavior and InvokeCommandAction classes to invoke one or more commands when data changes. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the DataChangedBehavior and InvokeMethodAction classes to invoke one or more methods when data changes.

Invoking a Method when Data Changes

The DataChangedBehavior class listens for the bound data to meet a specified condition, and executes one or more actions in response. It requires you to set the following properties:

  • Binding – an object that represents the bound object that the behavior will listen to.
  • ComparisonCondition – a ComparisonCondition enumeration value that represents the comparison to be performed between the values of the Binding and Value properties. The enumeration values are: Equal, NotEqual, LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual.
  • Value – an object that represents the value to be compared with the value of the Binding property.
  • Actions – one or more actions that should be executed in response to the bound data changing. Note that this property is set indirectly.

The InvokeMethodAction class executes a specified method when invoked. It requires you to set a TargetObject property to an object that exposes the method of interest, and a MethodName property to the name of the method to be invoked. The InvokeMethodAction class allows you to call a method with zero parameters, or a method with two parameters. For more information about calling a method with parameters, see EventHandlerBehavior and InvokeMethodAction.

Calling a Method without Parameters

The following code shows an example of using the DataChangedBehavior and InvokeMethodAction classes to invoke a method without parameters:

<StackLayout BindingContext="{x:Reference page}"> <Picker x:Name="picker" Title="Colours"> <Picker.Items> <x:String>Red</x:String> <x:String>Blue</x:String> <x:String>Green</x:String> </Picker.Items> <Picker.Behaviors> <behaviors:DataChangedBehavior Binding="{Binding Path=SelectedIndex, Source={x:Reference picker}}" ComparisonCondition="NotEqual" Value="-1"> <behaviors:InvokeMethodAction TargetObject="{Binding}" MethodName="OnPickerChanged" /> </behaviors:DataChangedBehavior> </Picker.Behaviors> </Picker> <StackLayout Orientation="Horizontal"> <Label Text="Selected Item:" /> <Label x:Name="selectedItemLabel" /> </StackLayout> </StackLayout>

When the value of the Picker.SelectedIndex property becomes not equal to –1, the OnPickerChanged method is executed. The TargetObject property value specifies that the BindingContext exposes the method of interest. Therefore, the InvokeMethodAction class will search the BindingContext of the attached control for the method, which in this case is the ContentPage. Note that the Actions property of the DataChangedBehavior is set indirectly by creating the InvokeMethodAction instance as a child of the DataChangedBehavior instance.

Generally, combining the DataChangedBehavior and InvokeMethodAction classes offers no advantage over combining the DataChangedBehavior and InvokeCommandAction classes. However, the InvokeMethodAction class can be useful when combined with other behaviors.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The DataChangedBehavior class listens for the bound data to meet a specified condition, and executes one or more actions in response. The InvokeMethodAction class executes a specified method when invoked. Generally, combining the DataChangedBehavior and InvokeCommandAction classes is preferred over combining the DataChangedBehavior and InvokeMethodAction classes. However, the InvokeMethodAction class can be useful when combined with other behaviors.

Monday, 21 March 2016

Xamarin.Forms Behaviors: DataChangedBehavior and InvokeCommandAction

Previously, I demonstrated using the EventHandlerBehavior and SetPropertyAction classes to set one or more properties when an event fires. The Behaviors Library for Xamarin.Forms has the notion of behaviors and actions. A behavior is attached to a control and listens for something to happen, such as an event firing. When the “something” happens, it triggers one or more actions, such as invoking a method or command. Actions are invoked by behaviors and executed on a selected control.

In this blog post, I’ll demonstrate using the DataChangedBehavior and InvokeCommandAction classes to invoke one or more commands when data changes.

Invoking a Command when Data Changes

The DataChangedBehavior class listens for the bound data to meet a specified condition, and executes one or more actions in response. It requires you to set the following properties:

  • Binding – an object that represents the bound object that the behavior will listen to.
  • ComparisonCondition – a ComparisonCondition enumeration value that represents the comparison to be performed between the values of the Binding and Value properties. The enumeration values are: Equal, NotEqual, LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual.
  • Value – an object that represents the value to be compared with the value of the Binding property.
  • Actions – one or more actions that should be executed in response to the bound data changing. Note that this property is set indirectly.

The InvokeCommandAction class executes a specified ICommand when invoked. It requires you to set a Command property to an ICommand instance, and CommandParameter and Converter properties can be optionally set. The CommandParameter property should be set to an object instance, with the Converter property being set to an instance of a class that implements IValueConverter. The ICommand specified in the Command property will then be executed, with the CommandParameter and Converter values being used if specified.

The following code shows an example of using the DataChangedBehavior to invoke a command:

<ContentPage.BindingContext> <local:InvokeCommandDemoPageViewModel /> </ContentPage.BindingContext> ... <Entry x:Name="entry" Placeholder="Enter Xamarin here"> <Entry.Behaviors> <behaviors:DataChangedBehavior Binding="{Binding Path=Text, Source={x:Reference entry}}" ComparisonCondition="Equal" Value="Xamarin"> <behaviors:InvokeCommandAction Command="{Binding OutputMessageCommand}" CommandParameter="{Binding Path=Text, Source={x:Reference entry}}" /> </behaviors:DataChangedBehavior> </Entry.Behaviors> </Entry> <Label Text="{Binding MessageText}" />

When the value of the Entry.Text property becomes equal to “Xamarin”, the OutputMessageCommand is executed. The InvokeCommandAction class expects to find the ICommand instance on the BindingContext of the attached object, and in this case the BindingContext has been set by a parent element to an instance of the InvokeCommandDemoPageViewModel class. The CommandParameter passes the value of the Entry.Text property to the Execute delegate of the Command. Note that the Actions property of the DataChangedBehavior is set indirectly by creating the InvokeCommandAction instance as a child of the DataChangedBehavior instance.

The advantage of using the DataChangedBehavior and InvokeCommandAction classes is that commands can be executed in response to data changing, removing boiler-plate code from code-behind files.

The sample application that this code comes from can be downloaded from GitHub.

Summary

The DataChangedBehavior class listens for the bound data to meet a specified condition, and executes one or more actions in response. The InvokeCommandAction class executes a specified ICommand when invoked. By using these two classes, commands can be executed in response to data changing, removing boiler-plate code from code-behind files.