{"id":45918,"date":"2020-01-13T09:32:10","date_gmt":"2020-01-13T17:32:10","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/xamarin\/?p=45918"},"modified":"2020-01-13T09:16:28","modified_gmt":"2020-01-13T17:16:28","slug":"visual-state-manager","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/visual-state-manager\/","title":{"rendered":"Simplifying Visual State Manager with TargetName"},"content":{"rendered":"<p>The <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/xamarin-forms\/user-interface\/visual-state-manager\" target=\"_blank\" rel=\"noopener noreferrer\">Visual State Manager<\/a> (VSM) has been around since Xamarin.Forms 3.0, but we&#8217;re not done developing it. One of the things we really wanted to add is the ability to change a property on <em>any<\/em> child element within scope. Up until now, you could only set values of properties of the element you applied the VSM to. Recently a PR was merged that changes that for our new Xamarin.Forms 4.5 pre-release version. This functionality will add a lot of extra flexibility to the VSM. In this post I will tell you all about it and show you how to use it yourself.<\/p>\n<h2>What is the Visual State Manager?<\/h2>\n<p>If you are not familiar with the VSM at all, let us fill you in on that a little bit first. What you can do with the help of the VSM is define certain states for your element and together with that state you can determine how that element should look. For example, think of a button that has a different color when it&#8217;s disabled or when it&#8217;s focused.<\/p>\n<p>The button in this example can be any Xamarin.Forms <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/xamarin.forms.visualelement\" target=\"_blank\" rel=\"noopener noreferrer\">VisualElement<\/a> and the color can be any <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/xamarin-forms\/xaml\/bindable-properties\" target=\"_blank\" rel=\"noopener noreferrer\">bindable property<\/a>. While Xamarin.Forms has defined a couple of states for you, you are also able to define your own custom states. Below you can see a piece of XAML that defines the look of a <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/xamarin-forms\/user-interface\/layouts\/stack-layout\" target=\"_blank\" rel=\"noopener noreferrer\">StackLayout<\/a> when it is in a Normal or Invalid state. When we switch to the Invalid state the background color of the <code>StackLayout<\/code> where the VSM resides will become Azure. When we then switch back to Normal, no explicit values are defined and thus the background color will go back to its default value.<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;StackLayout x:Name=\"MyStackLayout\" HorizontalOptions=\"Center\" VerticalOptions=\"CenterAndExpand\"&gt;\r\n        &lt;VisualStateManager.VisualStateGroups&gt;\r\n                &lt;VisualStateGroup x:Name=\"ColorStates\"&gt;\r\n                    &lt;VisualState x:Name=\"Normal\" \/&gt;\r\n                    &lt;VisualState x:Name=\"Invalid\"&gt;\r\n                        &lt;VisualState.Setters&gt;\r\n                            &lt;Setter Property=\"BackgroundColor\" Value=\"Azure\"\/&gt;\r\n                        &lt;\/VisualState.Setters&gt;\r\n                    &lt;\/VisualState&gt;\r\n                &lt;\/VisualStateGroup&gt;\r\n            &lt;\/VisualStateManager.VisualStateGroups&gt;\r\n\r\n            &lt;Label x:Name=\"WelcomeLabel\" Text=\"Welcome to Xamarin.Forms!\" HorizontalTextAlignment=\"Start\" HorizontalOptions=\"Start\" \/&gt;\r\n\r\n            &lt;Label x:Name=\"CurrentState\"&gt;&lt;\/Label&gt;\r\n\r\n            &lt;Button x:Name=\"ToggleValidButton\" Text=\"Toggle State\" Clicked=\"ToggleValid_OnClicked\"&gt;&lt;\/Button&gt;\r\n    &lt;\/StackLayout&gt;<\/pre>\n<p>In the case of the above example we have a simple button that toggles the state. In a more real-life example the trigger might be an invalid data entry of sorts.<\/p>\n<h2>Setting State on Multiple Controls<\/h2>\n<p>If we continue on this path, you can imagine that the XAML will get very bloated, fast. If we also wanted to give the label and the button a specific style when the state becomes invalid, the XAML would start looking like below.<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;StackLayout x:Name=\"MyStackLayout\" HorizontalOptions=\"Center\" VerticalOptions=\"CenterAndExpand\"&gt;\r\n        &lt;VisualStateManager.VisualStateGroups&gt;\r\n            &lt;VisualStateGroup x:Name=\"ColorStates\"&gt;\r\n                &lt;VisualState x:Name=\"Normal\" \/&gt;\r\n                &lt;VisualState x:Name=\"Invalid\"&gt;\r\n                    &lt;VisualState.Setters&gt;\r\n                        &lt;Setter Property=\"BackgroundColor\" Value=\"Azure\"\/&gt;\r\n                    &lt;\/VisualState.Setters&gt;\r\n                &lt;\/VisualState&gt;\r\n            &lt;\/VisualStateGroup&gt;\r\n        &lt;\/VisualStateManager.VisualStateGroups&gt;\r\n\r\n        &lt;Label x:Name=\"WelcomeLabel\" Text=\"Welcome to Xamarin.Forms!\" HorizontalTextAlignment=\"Start\" HorizontalOptions=\"Start\"&gt;\r\n            &lt;VisualStateManager.VisualStateGroups&gt;\r\n                &lt;VisualStateGroup x:Name=\"ColorStates\"&gt;\r\n                    &lt;VisualState x:Name=\"Normal\" \/&gt;\r\n                    &lt;VisualState x:Name=\"Invalid\"&gt;\r\n                        &lt;VisualState.Setters&gt;\r\n                            &lt;Setter Property=\"TextColor\" Value=\"Red\"\/&gt;\r\n                        &lt;\/VisualState.Setters&gt;\r\n                    &lt;\/VisualState&gt;\r\n                &lt;\/VisualStateGroup&gt;\r\n            &lt;\/VisualStateManager.VisualStateGroups&gt;\r\n        &lt;\/Label&gt;\r\n\r\n        &lt;Label x:Name=\"CurrentState\"&gt;&lt;\/Label&gt;\r\n\r\n        &lt;Button x:Name=\"ToggleValidButton\" Text=\"Toggle State\" Clicked=\"ToggleValid_OnClicked\"&gt;\r\n            &lt;VisualStateManager.VisualStateGroups&gt;\r\n                &lt;VisualStateGroup x:Name=\"ColorStates\"&gt;\r\n                    &lt;VisualState x:Name=\"Normal\" \/&gt;\r\n                    &lt;VisualState x:Name=\"Invalid\"&gt;\r\n                        &lt;VisualState.Setters&gt;\r\n                            &lt;Setter Property=\"TextColor\" Value=\"Red\"\/&gt;\r\n                        &lt;\/VisualState.Setters&gt;\r\n                    &lt;\/VisualState&gt;\r\n                &lt;\/VisualStateGroup&gt;\r\n            &lt;\/VisualStateManager.VisualStateGroups&gt;\r\n        &lt;\/Button&gt;\r\n    &lt;\/StackLayout&gt;<\/pre>\n<p>Can you spot the problem? We will have to repeat the whole VSM part for each control that we want to have these states on. Wouldn&#8217;t it be much easier if we could just reach into child elements within the same scope and set the properties directly from one central Visual State definition?<\/p>\n<p>While the visual representation is in this case not particularly important, or pretty, let us show you the app when the code is running.<\/p>\n<p><figure id=\"attachment_45913\" aria-labelledby=\"figcaption_attachment_45913\" class=\"wp-caption aligncenter\" ><img decoding=\"async\" class=\"wp-image-45913 size-full\" src=\"http:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2019\/12\/Untitled.gif\" alt=\"Visual State Manager in Action\" width=\"356\" height=\"740\" \/><figcaption id=\"figcaption_attachment_45913\" class=\"wp-caption-text\">Visual State Manager in Action<\/figcaption><\/figure><\/p>\n<h2>Using TargetName with Visual State Manager<\/h2>\n<p>With the new functionality that is added, we can solve the above problem with significantly less XAML. And if there is one thing I love more than XAML, it&#8217;s less XAML.<\/p>\n<p>Let&#8217;s have another look at the above situation, but now with the help of the <code>TargetName<\/code> we introduced on the <code>Setter<\/code> object.<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;StackLayout x:Name=\"MyStackLayout\" HorizontalOptions=\"Center\" VerticalOptions=\"CenterAndExpand\"&gt;\r\n        &lt;VisualStateManager.VisualStateGroups&gt;\r\n            &lt;VisualStateGroup x:Name=\"ColorStates\"&gt;\r\n                &lt;VisualState x:Name=\"Normal\" \/&gt;\r\n                &lt;VisualState x:Name=\"Invalid\"&gt;\r\n                    &lt;VisualState.Setters&gt;\r\n                        &lt;Setter Property=\"BackgroundColor\" Value=\"Azure\"\/&gt;\r\n\r\n                        &lt;!-- Added the two lines below --&gt;\r\n                        &lt;Setter TargetName=\"WelcomeLabel\" Property=\"Label.TextColor\" Value=\"Red\"\/&gt;\r\n                        &lt;Setter TargetName=\"ToggleValidButton\" Property=\"Button.TextColor\" Value=\"Red\"\/&gt;\r\n                        &lt;!-- Look here! Added the two lines above --&gt;\r\n\r\n                    &lt;\/VisualState.Setters&gt;\r\n                &lt;\/VisualState&gt;\r\n            &lt;\/VisualStateGroup&gt;\r\n        &lt;\/VisualStateManager.VisualStateGroups&gt;\r\n\r\n        &lt;Label x:Name=\"WelcomeLabel\" Text=\"Welcome to Xamarin.Forms!\" HorizontalTextAlignment=\"Start\" HorizontalOptions=\"Start\" \/&gt;\r\n\r\n        &lt;Label x:Name=\"CurrentState\"&gt;&lt;\/Label&gt;\r\n\r\n        &lt;Button x:Name=\"ToggleValidButton\" Text=\"Toggle State\" Clicked=\"ToggleValid_OnClicked\"&gt;&lt;\/Button&gt;\r\n    &lt;\/StackLayout&gt;<\/pre>\n<p>Notice how I have now just added two lines in the <code>VisualState.Setters<\/code> collection. With the new <code>TargetName<\/code> property I am able to reference other elements by its name. Instead of having to repeat the whole visual state XAML, I can now just add these two lines to directly. That way, I can access the elements I want to change some properties on. Note that when you use it like this, you will have to specify the full path to the property in the <code>Property<\/code> attribute. For example, if you want to set the <code>TextColor<\/code> on a <code>Label<\/code>, you will have to specify it as <code>Label.TextColor<\/code>. The implementation at this time only works for bindable properties.<\/p>\n<h2>Learn More<\/h2>\n<p>When you want to read more on the Visual State Manager, head over to <a href=\"https:\/\/docs.microsoft.com\/xamarin\/xamarin-forms\/user-interface\/visual-state-manager\" target=\"_blank\" rel=\"noopener noreferrer\">the documentation pages<\/a>. Code from this post can be found at <a href=\"https:\/\/github.com\/jfversluis\/VSMTargetSample\/\" target=\"_blank\" rel=\"noopener noreferrer\">this sample repository<\/a>, use it to give it a try yourself. If you are interested in the actual PR, you can have a look <a href=\"https:\/\/github.com\/xamarin\/Xamarin.Forms\/pull\/8144\">here<\/a>. And of course, a big thank you to the original author that did most of the work for this.<\/p>\n<p>Besides this change there is a lot of other (upcoming) awesome stuff in the 4.5 release of Xamarin.Forms. Do you have more ideas on how to improve the VSM itself? Please don&#8217;t hesitate to <a href=\"https:\/\/github.com\/xamarin\/Xamarin.Forms\/issues\/new?assignees=&amp;labels=proposal-open%2C+t%2Fenhancement+%E2%9E%95&amp;template=feature_request.md&amp;title=%5BEnhancement%5D+YOUR+IDEA%21\" target=\"_blank\" rel=\"noopener noreferrer\">open an issue<\/a> and let us know!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Visual State Manager (VSM) can now change a property on any child element within scope for our new Xamarin.Forms 4.5 pre-release version.<\/p>\n","protected":false},"author":13350,"featured_media":45913,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[313,2,303,6602,367],"tags":[5,6,7553,7552,7551,16,5841],"class_list":["post-45918","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-developers","category-ios","category-visual-studio","category-xamarin-forms","tag-android","tag-ios","tag-targetname","tag-visual-state-manager","tag-vsm","tag-xamarin-forms","tag-xaml"],"acf":[],"blog_post_summary":"<p>The Visual State Manager (VSM) can now change a property on any child element within scope for our new Xamarin.Forms 4.5 pre-release version.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/45918","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\/13350"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=45918"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/45918\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/45913"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=45918"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=45918"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=45918"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}