{"id":35538,"date":"2018-02-16T13:48:28","date_gmt":"2018-02-16T18:48:28","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=35538"},"modified":"2018-02-16T13:48:28","modified_gmt":"2018-02-16T18:48:28","slug":"extend-xamarin-forms-controls-functionality-with-behaviors","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/extend-xamarin-forms-controls-functionality-with-behaviors\/","title":{"rendered":"Extend Xamarin.Forms Controls Functionality with Behaviors"},"content":{"rendered":"<p>\t\t\t\tXamarin.Forms provides a way to build 100% native, cross-platform applications with both a shared logic layer and a shared user-interface layer. Built-in Xamarin.Forms controls also provide a ton of functionality out-of-the-box to create some amazing apps.<\/p>\n<p>That said, mobile app developers are a crazy and creative bunch, and it would be impossible for the Xamarin.Forms engineers to create APIs for the controls that covered every conceivable scenario we come up with. That&#8217;s where <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/application-fundamentals\/behaviors\/\">Xamarin.Forms Behaviors<\/a> come in!<\/p>\n<p>These little gems of awesomeness allow you to attach additional functionality to a Xamarin.Forms control (actually, any Xamarin.Forms <code>View<\/code>\u00a0) without having to subclass that control or write any messy code in the code-behind page. That&#8217;s because Behaviors are written as their own classes, and stand by themselves. Not only that, you can also attach more than one Behavior to a single control!<\/p>\n<h2>Write Your First Xamarin.Forms Behavior<\/h2>\n<p>Let&#8217;s take a look at how you can build a simple Behavior. This Behavior will attach a validation routine to a <code>Picker<\/code>\u00a0control. The validation routine will change the background color of the <code>Picker<\/code> if the currently selected item&#8217;s text is not in a preset list of valid values.<\/p>\n<p>The end result will look like the following (and of course it validates a favored topic\u2014beards!):<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-35631\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/blog.gif\" alt=\"\" width=\"336\" height=\"600\" \/><\/p>\n<h3>Behaviors Methods<\/h3>\n<p>To start with, all behaviors must inherit from the <code>Behavior&lt;T&gt;<\/code>\u00a0class.<\/p>\n<pre class=\"lang:c# decode:true \">public class SimplePickerValidator : Behavior&lt;Picker&gt;\n{\n    protected override void OnAttachedTo(Picker bindable)\n    {\n        base.OnAttachedTo(bindable);\n    }\n\n    protected override void OnDetachingFrom(Picker bindable)\n    {\n        base.OnDetachingFrom(bindable);\n    }\n}<\/pre>\n<p>There are two methods that we override here:<\/p>\n<ol>\n<li><code>OnAttachedTo<\/code>: Gets invoked whenever the behavior is attached to the <code>Picker<\/code>.<\/li>\n<li><code>OnDetachingFrom<\/code>: Is naturally invoked when the behavior is being removed from the <code>Picker<\/code>.<\/li>\n<\/ol>\n<p>Note that a strongly typed <code>Picker<\/code>\u00a0is passed in to both methods. This is because we inherited from <code>Behavior&lt;Picker&gt;<\/code>.<\/p>\n<p>When implementing a behavior, you&#8217;ll generally want to handle an event that the host control emits. Inside that event handler, you&#8217;ll be able to add the additional functionality, or additional behavior, to the control. So, the <code>OnAttachedTo<\/code>\u00a0becomes the place to subscribe to the event, while the <code>OnDetachingFrom<\/code>\u00a0becomes the place to unsubscribe from the same event.<\/p>\n<p>This <code>SimplePickerValidator<\/code> behavior now looks like this:<\/p>\n<pre class=\"lang:c# decode:true\">public class SimplePickerValidator : Behavior&lt;Picker&gt;\n{\n\n    protected override void OnAttachedTo(Picker bindable)\n    {\n        bindable.SelectedIndexChanged += Bindable_SelectedIndexChanged;\n    }\n\n    protected override void OnDetachingFrom(Picker bindable)\n    {\n        bindable.SelectedIndexChanged -= Bindable_SelectedIndexChanged;\n    }\n\n    void Bindable_SelectedIndexChanged(object sender, EventArgs e)\n    {\n\n    }\n}<\/pre>\n<h3>Implementing<\/h3>\n<p>Before implementing the <code>Bindable_SelectedIndexChanged<\/code>\u00a0method, there needs to be a way for the calling code, like the XAML page, to specify what the correct values are for this behavior to validate against.<\/p>\n<p>Bindable properties<a href=\"#foot1\"><sup>1<\/sup><\/a> to the rescue! That&#8217;s right, behaviors can contain bindable properties, just like any other Xamarin.Forms control. Add a property called <code>ValidValues<\/code> like so:<\/p>\n<pre class=\"lang:c# decode:true\">public class SimplePickerValidator : Behavior&lt;Picker&gt;\n{\n    static readonly BindableProperty ValidValuesProperty =\n        BindableProperty.Create(nameof(ValidValues), typeof(string[]), typeof(PickerColorBehavior));\n\n    public string[] ValidValues\n    {\n        get =&gt; (string[])GetValue(ValidValuesProperty);\n        set =&gt; SetValue(ValidValuesProperty, value);\n    }\n\n    protected override void OnAttachedTo(Picker bindable)\n    {\n        bindable.SelectedIndexChanged += Bindable_SelectedIndexChanged;\n    }\n\n    protected override void OnDetachingFrom(Picker bindable)\n    {\n        bindable.SelectedIndexChanged -= Bindable_SelectedIndexChanged;\n    }\n\n    void Bindable_SelectedIndexChanged(object sender, EventArgs e)\n    {\n\n    }\n}<\/pre>\n<p>Finally, implement the logic of <code>Bindable_SelectedIndexChanged<\/code>:<\/p>\n<pre class=\"lang:c# decode:true \">void Bindable_SelectedIndexChanged(object sender, EventArgs e)\n{\n    \/\/ Bound and cast to a picker\n    if (!(sender is Picker bindable))\n        return;\n\n    \/\/ Make sure the picker is data bound\n    if (!(bindable.ItemDisplayBinding is Binding displayBinding))\n        return;\n\n    \/\/ Get the binding's path\n    var displayBindingPath = displayBinding.Path;\n\n    \/\/ Use reflection to get the value of the selected item of the picker\n    var selectedItem = bindable.SelectedItem.GetType().GetRuntimeProperty(displayBindingPath);\n    var selectedText = selectedItem.GetValue(bindable.SelectedItem);\n\n    \/\/ Check to see if everything is valid\n    if (ValidValues != null &amp;&amp; ValidValues.Contains(selectedText))\n    {\n        IsValid = true;\n        bindable.BackgroundColor = Color.Default;\n    }\n    else\n    {\n        IsValid = false;\n        bindable.BackgroundColor = Color.Salmon;\n    }\n}<\/pre>\n<p>Here&#8217;s what&#8217;s going on in the above event handler: because the behavior is checking to see whether the displayed value in a data-bound <code>Picker<\/code>\u00a0is equal to a value in an array, you first need to get that value out. You can use reflection to get to the text displayed in a <code>Picker<\/code>&#8216;s\u00a0data binding.<a href=\"#foot2\"><sup>2<\/sup><\/a><\/p>\n<p>Once the value is in <code>selectedText<\/code>, check to see if that exists in the <code>ValidValues<\/code> array.<\/p>\n<h3>Adding Behaviors<\/h3>\n<p>The very last step is to add this behavior to a control. In XAML, it would look like this:<\/p>\n<pre class=\"lang:Xaml decode:true \">&lt;Picker Title=\"Rate Your Beard\" \n    ItemsSource=\"{Binding BeardRatings}\" \n    SelectedItem=\"{Binding SelectedBeardRating}\" \n    ItemDisplayBinding=\"{Binding Description}\"&gt;\n\n    &lt;Picker.Behaviors&gt;\n        &lt;local:PickerColorBehavior \n            ValidValues=\"{x:Static local:BehaviorsPageViewModel.ValidRatings}\" \/&gt;\n    &lt;\/Picker.Behaviors&gt;\n    \n&lt;\/Picker&gt;<\/pre>\n<blockquote style=\"text-align: left;font-size: 12px;padding: 10px 20px;border-left: 3px solid #2c3e50\"><p>Note the <code>&lt;Picker.Behaviors&gt;<\/code>\u00a0property is the collection where this (and any other Behaviors) are added, and that the <code>local<\/code>\u00a0XAML namespace was defined elsewhere.<\/p><\/blockquote>\n<h2>That Easy!<\/h2>\n<p>With that, you now have a reusable behavior that can be set up to validate whether a selected item is in a preset array. Check out the <a href=\"https:\/\/msou.co\/bdy\">full working solution in GitHub<\/a> that demonstrates this behavior, as well as another behavior that adds a command to an <code>Entry<\/code> control to be fired every time the text changes.<\/p>\n<p>Behaviors can also add commands to controls that don&#8217;t already have them. Imagine having a command for the <code>ListView.ItemSelected<\/code>\u00a0event; a behavior can do <a href=\"https:\/\/github.com\/xamarin\/xamarin-forms-samples\/blob\/master\/Behaviors\/EventToCommandBehavior\/EventToCommandBehavior\/Behaviors\/EventToCommandBehavior.cs\" target=\"_blank\" rel=\"noopener\">that<\/a>! More information about creating these types of Behaviors can be found in the <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/application-fundamentals\/behaviors\/reusable\/event-to-command-behavior\/\">documentation<\/a>. For even more info, check out the episode of the <a href=\"https:\/\/msou.co\/bdx\">Xamarin Show<\/a> where James Montemagno and Matt go over the ins and outs of behaviors.<\/p>\n<p>The Xamarin community has contributed several behaviors to an open source project called <a href=\"https:\/\/github.com\/xamarin\/XamarinCommunityToolkit\">The Xamarin Community Toolkit<\/a>. Head there to see even more examples of how behaviors are built, reuse some of the ones there, and contribute your own!<\/p>\n<p>Behaviors allow developers to attach additional functionality to Xamarin.Forms <code>Views<\/code>, without the need to subclass the <code>View<\/code>\u00a0or mess with the code-behind, and to add more than a single behavior to a <code>View<\/code>. By making your behavior standalone, you can reuse them across all of your applications!<\/p>\n<p><sup id=\"foot1\">1<\/sup>If you&#8217;re using a Behavior in a Xamarin.Forms style, do not use Bindable Properties. Here a <code>&lt;BindableObject, StateInstance&gt;<\/code> is a better choice.\n<sup id=\"foot2\">2<\/sup>An assumption that the binding is of a type <code>Binding<\/code> is being made here, and that there are not indexers in the binding path, for convenience.<\/p>\n<p><a href=\"https:\/\/forums.xamarin.com\/123407\/extend-xamarin-forms-controls-functionality-with-behaviors\">Discuss this post on the forums!<\/a>\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Xamarin.Forms provides a way to build 100% native, cross-platform applications with both a shared logic layer and a shared user-interface layer. Built-in Xamarin.Forms controls also provide a ton of functionality out-of-the-box to create some amazing apps. That said, mobile app developers are a crazy and creative bunch, and it would be impossible for the Xamarin.Forms [&hellip;]<\/p>\n","protected":false},"author":569,"featured_media":35631,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[16],"class_list":["post-35538","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>Xamarin.Forms provides a way to build 100% native, cross-platform applications with both a shared logic layer and a shared user-interface layer. Built-in Xamarin.Forms controls also provide a ton of functionality out-of-the-box to create some amazing apps. That said, mobile app developers are a crazy and creative bunch, and it would be impossible for the Xamarin.Forms [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/35538","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/569"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=35538"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/35538\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=35538"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=35538"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=35538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}