Jekyll2024-01-01T14:11:58+00:00http://evgenyzborovsky.com/feed.xmlEvgeny ZborovskyEngineering Manager | Former Microsoft MVPEvgeny ZborovskyUsing Native Facebook Login Button in Xamarin.Forms QA2019-09-10T00:00:00+00:002019-09-10T00:00:00+00:00http://evgenyzborovsky.com/2019/09/10/facebook-sdk-qa<p>On 9th of March 2018 I wrote an article “<a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">Using Native Facebook Login Button in Xamarin.Forms</a>” which turned out to be the second popular article on my blog. Since then, thanks for my readers, I received many additional questions which I decided to answer in this separate article. However, before diving into those questions, I would like to take a step back and talk about Facebook SDK in relation to Xamarin.</p>
<p><a href="https://github.com/xamarin/FacebookComponents">Facebook SDK</a> is available for Xamarin.Android and Xamarin.iOS but not for Xamarin.Forms. This might be the most confusing part, especially if you are working with Facebook SDK on Xamarin.Forms for the first time. Luckily, the problem could be easily solved, please follow the <a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">original article</a>.</p>
<p>Now the question is “Do you actually need to integrate the official Facebook Login component to your app?”. What if you want a fully customised button instead of the official look and feel? What if you just want to obtain an authentication token from Facebook and pass it to your backend? By the end of the day we just want to be productive and write as less code as possible, right? If I just described your case please refer to my <a href="/2018/08/08/retrieving-facebook-user-access-token-in-xamarin-forms/">other article</a> where this can be achieved with a couple lines of code with a <a href="https://github.com/CrossGeeks/FacebookClientPlugin">ready made wrapper</a> for Xamarin.Forms.</p>
<p>If for some reason you are still willing to use the official Facebook Login component or it is already integrated and there is a need in a slight modification/enhancement please follow the QA section and hopefully you will find the answer for your question in there.</p>
<h2 id="qa">QA</h2>
<h3 id="is-it-possible-to-change-the-button-label">Is it possible to change the button label?</h3>
<p>We have to keep in mind that Facebook Login button is smart enough to represent the current state and there should be at least 2 labels: Login and Logout. In case of Android it is possible as <code class="language-plaintext highlighter-rouge">Xamarin.Facebook.Login.Widget.LoginButton</code> has a dedicated method for each state <code class="language-plaintext highlighter-rouge">SetLoginText</code> and <code class="language-plaintext highlighter-rouge">SetLogoutText</code>. Unfortunately on iOS those methods are not available. We could use the <code class="language-plaintext highlighter-rouge">SetAttributedTitle</code> method, however, this will result on a static label and will completely ignore the states unless you will handle those state changes explicitly.</p>
<h3 id="is-it-possible-to-catch-the-logout-event">Is it possible to catch the logout event?</h3>
<p>There are some platform differences, where on iOS you could simply catch and response to logout event on the Facebook Login button level, where on Android you could not. In order to keep the solution somewhat consistent, I solved the problem by listening to the <code class="language-plaintext highlighter-rouge">Facebook.CoreKit.AccessToken.DidChangeNotification</code> on iOS and by extending the <code class="language-plaintext highlighter-rouge">Xamarin.Facebook.AccessTokenTracker</code> abstract class on Android. In both cases an old token and a new one are provided so you could act accordingly. I updated the existing <a href="https://github.com/yuv4ik/XFFacebookLoginButtonExample">github repo</a> where you can find those implementations.</p>
<h3 id="is-it-possible-to-logout-programmatically">Is it possible to logout programmatically?</h3>
<p>On Android there is a <code class="language-plaintext highlighter-rouge">LoginManager</code> singleton class which expose the <code class="language-plaintext highlighter-rouge">LogOut</code> method, where on iOS you will have to create an instance of <code class="language-plaintext highlighter-rouge">LoginManager</code> and use the same <code class="language-plaintext highlighter-rouge">LogOut</code> method. Example can be found in the <a href="https://github.com/yuv4ik/XFFacebookLoginButtonExample">github repo</a>.</p>
<h3 id="is-it-possible-to-retrieve-the-first-name-or-email-of-the-logged-in-user">Is it possible to retrieve the first name or email of the logged in user?</h3>
<p>Usually this is done by the backend. The application will send the Facebook authentication token to the backend and the backend will take care of retrieving the profile information in order to create an account in your system. However, you could create a Facebook Graph request on the app side as well and request the necessary information about the user, using the login token.</p>
<h3 id="unhandled-exception-is-thrown-on-android-xamarinfacebookfacebooksdknotinitializedexception-the-sdk-has-not-been-initialized-make-sure-to-call-facebooksdksdkinitialize-first">Unhandled Exception is thrown on Android: Xamarin.Facebook.FacebookSdkNotInitializedException: The SDK has not been initialized, make sure to call FacebookSdk.sdkInitialize() first.</h3>
<p>Please make sure to define the Facebook App ID correctly as described in the <a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">original post</a> (Android/2/3/4). In short <code class="language-plaintext highlighter-rouge">Strings.xml</code> and <code class="language-plaintext highlighter-rouge">AndroidManifest.xml</code> should contain Facebook App ID and Name. Additionally, make sure to use the latest and greatest NuGet packages.</p>
<h2 id="post-scriptum">Post scriptum</h2>
<p>All the code examples are available on <a href="https://github.com/yuv4ik/XFFacebookLoginButtonExample">GitHub</a>. The repository is updated to latest and greatest NuGet packages and contains additional examples.</p>Evgeny ZborovskyOn 9th of March 2018 I wrote an article “Using Native Facebook Login Button in Xamarin.Forms” which turned out to be the second popular article on my blog. Since then, thanks for my readers, I received many additional questions which I decided to answer in this separate article. However, before diving into those questions, I would like to take a step back and talk about Facebook SDK in relation to Xamarin.Mocking Xamarin.Essentials2019-01-09T00:00:00+00:002019-01-09T00:00:00+00:00http://evgenyzborovsky.com/2019/01/09/mocking-xamarin-essentials<blockquote>
<p>Xamarin.Essentials provides developers with cross-platform APIs for their mobile applications.</p>
</blockquote>
<p>If you never heard about Xamarin.Essentials you should get familiar with it as soon as possible! It is a great collection of APIs that is very easy to use and integrate to your projects. You can find more information in the <a href="https://docs.microsoft.com/en-us/xamarin/essentials/">official documentation</a>.</p>
<p>In order to keep the things as simple as possible and easy as possible to pick up for new contributors, all the APIs are written in a static way. The first reaction of developers would be to immediately raise their eyebrows and ask: “Why so? How are we going to unit test that?”. The answer in most cases is easier than you may think at first.</p>
<p>Before we will talk about Xamarin.Essentials specifically, think for a moment how would you mock the static <code class="language-plaintext highlighter-rouge">DateTimeOffset.Now</code> or any other static API? One way is to use <a href="https://docs.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2017">Shims</a> but that has quite a lot of limitations and implications on the project side. Another way, that I tend to use quite a lot is to create a simple wrapper class around the static API. For example:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">namespace</span> <span class="nn">XFMockingXamarinEssentials</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">interface</span> <span class="nc">IDateTimeOffsetWrapper</span>
<span class="p">{</span>
<span class="n">DateTimeOffset</span> <span class="n">Now</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">DateTimeOffsetWrapper</span> <span class="p">:</span> <span class="n">IDateTimeOffsetWrapper</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">DateTimeOffset</span> <span class="n">Now</span> <span class="p">=></span> <span class="n">DateTimeOffset</span><span class="p">.</span><span class="n">Now</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>This way we will be able to inject <code class="language-plaintext highlighter-rouge">IDateTimeOffsetWrapper</code> and mock the <code class="language-plaintext highlighter-rouge">Now</code> property when it is necessary. Same technique can be applied to any static API. Now back to Xamarin.Essentials.</p>
<p>Xamarin.Essentials contains quite a lot of APIs for 3 different platforms. Typically there is no need to use all of those in a single project but just a few. So for example we would like to use:</p>
<ul>
<li>Connectivity - for checking if the device is connected to internet</li>
<li>SecureStorage - for keeping sensitive data that should be encrypted</li>
</ul>
<p>Using the above example we could create 2 wrappers for our specific needs:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">namespace</span> <span class="nn">XFMockingXamarinEssentials</span>
<span class="p">{</span>
<span class="k">using</span> <span class="nn">Xamarin.Essentials</span><span class="p">;</span>
<span class="k">public</span> <span class="k">interface</span> <span class="nc">IConnectivityWrapper</span>
<span class="p">{</span>
<span class="kt">bool</span> <span class="nf">IsConnectedToInternet</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ConnectivityWrapper</span> <span class="p">:</span> <span class="n">IConnectivityWrapper</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="nf">IsConnectedToInternet</span><span class="p">()</span> <span class="p">=></span> <span class="n">Connectivity</span><span class="p">.</span><span class="n">NetworkAccess</span> <span class="p">==</span> <span class="n">NetworkAccess</span><span class="p">.</span><span class="n">Internet</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">namespace</span> <span class="nn">XFMockingXamarinEssentials</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">interface</span> <span class="nc">ISecuredStorageWrapper</span>
<span class="p">{</span>
<span class="n">Task</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="nf">GetAuthToken</span><span class="p">();</span>
<span class="n">Task</span> <span class="nf">SetAuthToken</span><span class="p">(</span><span class="kt">string</span> <span class="n">token</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">SecuredStorageWrapper</span> <span class="p">:</span> <span class="n">ISecuredStorageWrapper</span>
<span class="p">{</span>
<span class="k">const</span> <span class="kt">string</span> <span class="n">tokenKey</span> <span class="p">=</span> <span class="s">"auth_token"</span><span class="p">;</span>
<span class="k">public</span> <span class="n">Task</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="nf">GetAuthToken</span><span class="p">()</span> <span class="p">=></span> <span class="n">Xamarin</span><span class="p">.</span><span class="n">Essentials</span><span class="p">.</span><span class="n">SecureStorage</span><span class="p">.</span><span class="nf">GetAsync</span><span class="p">(</span><span class="n">tokenKey</span><span class="p">);</span>
<span class="k">public</span> <span class="n">Task</span> <span class="nf">SetAuthToken</span><span class="p">(</span><span class="kt">string</span> <span class="n">token</span><span class="p">)</span> <span class="p">=></span> <span class="n">Xamarin</span><span class="p">.</span><span class="n">Essentials</span><span class="p">.</span><span class="n">SecureStorage</span><span class="p">.</span><span class="nf">SetAsync</span><span class="p">(</span><span class="n">tokenKey</span><span class="p">,</span> <span class="n">token</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Easy as it is, now we can mock the data and unit test functionality that is relying on those wrappers. Additional advantage of using wrappers in this case, is that you could painlessly replace Xamarin.Essentials by your own or a third party implementation just within the wrapper itself. Does not happen often but still may.</p>
<p>The down side of this approach is that we have to create wrappers again and again within a single project or from project to project, luckily there is a solution for that as well! There is a great project <a href="https://github.com/rdavisau/essential-interfaces">Interfaces for Xamarin.Essentials</a> that generates interfaces for you and if you don’t want to introduce another dependency to your project, it is also possible to just copy auto-generated interfaces from <a href="https://essential-interfaces.azurewebsites.net/">here</a>. Thanks to Ryan Davis!</p>
<p>Another example when a wrapper can make sense is to check the running platform:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">namespace</span> <span class="nn">XFMockingXamarinEssentials</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">interface</span> <span class="nc">IRuntimePlatformWrapper</span>
<span class="p">{</span>
<span class="kt">bool</span> <span class="nf">IsOnAndroid</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">RuntimePlatformWrapper</span> <span class="p">:</span> <span class="n">IRuntimePlatformWrapper</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="nf">IsOnAndroid</span><span class="p">()</span> <span class="p">=></span> <span class="n">Device</span><span class="p">.</span><span class="n">RuntimePlatform</span> <span class="p">==</span> <span class="n">Device</span><span class="p">.</span><span class="n">Android</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>As you see it is a pretty simple yet powerful technique that you can apply anywhere. Cheers!</p>
<p>P.S.: GitHub repository is available <a href="https://github.com/yuv4ik/XFEssentialsMockExample">here</a>.</p>Evgeny ZborovskyXamarin.Essentials provides developers with cross-platform APIs for their mobile applications.Dynamically changing the selected tab tint color in Xamarin.Forms2019-01-02T00:00:00+00:002019-01-02T00:00:00+00:00http://evgenyzborovsky.com/2019/01/02/dynamically-changing-the-selected-tab-tint-color-in-xamarin-forms<h3 id="android">Android</h3>
<p><img src="/images/2019-01-02-dynamically-changing-the-selected-tab-tint-color-in-xamarin-forms/2.gif" alt="droid" /></p>
<p>Since Xamarin.Forms 3.1 a <a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.platformconfiguration.androidspecific.tabbedpage.barselecteditemcolorproperty?view=xamarin-forms">TabbedPage.BarSelectedItemColor</a> property has been introduced and we can simply use it to achieve our goal.</p>
<p>XAML:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><TabbedPage</span>
<span class="na">xmlns:android=</span><span class="s">"clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"</span>
<span class="na">android:TabbedPage.BarSelectedItemColor=</span><span class="s">"Red"</span><span class="nt">></span>
<span class="nt"></TabbedPage></span></code></pre></figure>
<p>C#:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="n">Xamarin</span><span class="p">.</span><span class="n">Forms</span><span class="p">.</span><span class="n">PlatformConfiguration</span><span class="p">.</span><span class="n">AndroidSpecific</span><span class="p">.</span><span class="n">TabbedPage</span><span class="p">.</span><span class="nf">SetBarSelectedItemColor</span><span class="p">(%</span><span class="n">tabbedPage</span><span class="p">%,</span> <span class="p">%</span><span class="n">color</span><span class="p">%);</span></code></pre></figure>
<h3 id="ios">iOS</h3>
<p><img src="/images/2019-01-02-dynamically-changing-the-selected-tab-tint-color-in-xamarin-forms/2.gif" alt="ios" /></p>
<p>Unfortunately on iOS we have to implement the solution ourselves. Luckily there is a <a href="https://developer.apple.com/documentation/uikit/uitabbar/1623460-tintcolor">TintColor</a> property on a <code class="language-plaintext highlighter-rouge">UITabBar</code> that we can use.</p>
<h3 id="the-solution">The solution</h3>
<p>We will create an <code class="language-plaintext highlighter-rouge">Effect</code> using the knowledge listed above. The effect will have a single <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/effects/passing-parameters/attached-properties">AttachedProperty</a> which will represent the selected tab tint color:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">SelectedTabItemDynamicTintColorEffect</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">readonly</span> <span class="n">BindableProperty</span> <span class="n">SelectedTabTintColorProperty</span> <span class="p">=</span>
<span class="n">BindableProperty</span><span class="p">.</span><span class="nf">CreateAttached</span><span class="p">(</span><span class="s">"SelectedTabTintColor"</span><span class="p">,</span> <span class="k">typeof</span><span class="p">(</span><span class="n">Color</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="n">SelectedTabItemDynamicTintColorEffect</span><span class="p">),</span> <span class="n">Color</span><span class="p">.</span><span class="n">Default</span><span class="p">);</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">Color</span> <span class="nf">GetSelectedTabTintColor</span><span class="p">(</span><span class="n">BindableObject</span> <span class="n">view</span><span class="p">)</span> <span class="p">=></span> <span class="p">(</span><span class="n">Color</span><span class="p">)</span><span class="n">view</span><span class="p">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">SelectedTabTintColorProperty</span><span class="p">);</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">SetSelectedTabTintColor</span><span class="p">(</span><span class="n">BindableObject</span> <span class="n">view</span><span class="p">,</span> <span class="n">Color</span> <span class="k">value</span><span class="p">)</span> <span class="p">=></span> <span class="n">view</span><span class="p">.</span><span class="nf">SetValue</span><span class="p">(</span><span class="n">SelectedTabTintColorProperty</span><span class="p">,</span> <span class="k">value</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>Next we will create the <code class="language-plaintext highlighter-rouge">RoutingEffect</code>:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">TabbedPageSelectedTabItemDynamicTintColorEffect</span> <span class="p">:</span> <span class="n">RoutingEffect</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">TabbedPageSelectedTabItemDynamicTintColorEffect</span><span class="p">()</span> <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="s">$"XFDynamicSelectedTabTintColor.Effects.</span><span class="p">{</span><span class="k">nameof</span><span class="p">(</span><span class="n">TabbedPageSelectedTabItemDynamicTintColorEffect</span><span class="p">)}</span><span class="s">"</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Here is the Android implementation:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">TabbedPageSelectedTabItemDynamicTintColorEffect</span> <span class="p">:</span> <span class="n">PlatformEffect</span>
<span class="p">{</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnAttached</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnDetached</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnElementPropertyChanged</span><span class="p">(</span><span class="n">PropertyChangedEventArgs</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">base</span><span class="p">.</span><span class="nf">OnElementPropertyChanged</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">PropertyName</span> <span class="p">==</span> <span class="n">SelectedTabItemDynamicTintColorEffect</span><span class="p">.</span><span class="n">SelectedTabTintColorProperty</span><span class="p">.</span><span class="n">PropertyName</span><span class="p">)</span>
<span class="nf">SetTintColor</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">void</span> <span class="nf">SetTintColor</span><span class="p">()</span> <span class="p">=></span>
<span class="n">Xamarin</span><span class="p">.</span><span class="n">Forms</span><span class="p">.</span><span class="n">PlatformConfiguration</span><span class="p">.</span><span class="n">AndroidSpecific</span><span class="p">.</span><span class="n">TabbedPage</span><span class="p">.</span><span class="nf">SetBarSelectedItemColor</span><span class="p">(</span><span class="n">Element</span><span class="p">,</span> <span class="n">SelectedTabItemDynamicTintColorEffect</span><span class="p">.</span><span class="nf">GetSelectedTabTintColor</span><span class="p">(</span><span class="n">Element</span><span class="p">));</span>
<span class="p">}</span></code></pre></figure>
<p>Here is the iOS implementation:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">TabbedPageSelectedTabItemDynamicTintColorEffect</span> <span class="p">:</span> <span class="n">PlatformEffect</span>
<span class="p">{</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnAttached</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnDetached</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnElementPropertyChanged</span><span class="p">(</span><span class="n">PropertyChangedEventArgs</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">base</span><span class="p">.</span><span class="nf">OnElementPropertyChanged</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">PropertyName</span> <span class="p">==</span> <span class="n">SelectedTabItemDynamicTintColorEffect</span><span class="p">.</span><span class="n">SelectedTabTintColorProperty</span><span class="p">.</span><span class="n">PropertyName</span><span class="p">)</span>
<span class="nf">SetTintColor</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">void</span> <span class="nf">SetTintColor</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">tabBar</span> <span class="p">=</span> <span class="n">Container</span><span class="p">.</span><span class="n">Subviews</span><span class="p">.</span><span class="nf">First</span><span class="p">(</span><span class="n">v</span> <span class="p">=></span> <span class="n">v</span> <span class="k">is</span> <span class="n">UIKit</span><span class="p">.</span><span class="n">UITabBar</span><span class="p">);</span>
<span class="n">tabBar</span><span class="p">.</span><span class="n">TintColor</span> <span class="p">=</span> <span class="n">SelectedTabItemDynamicTintColorEffect</span><span class="p">.</span><span class="nf">GetSelectedTabTintColor</span><span class="p">(</span><span class="n">Element</span><span class="p">).</span><span class="nf">ToUIColor</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>In both cases we are monitoring <code class="language-plaintext highlighter-rouge">SelectedTabTintColorProperty</code> for changes and once changed simply applying a new <code class="language-plaintext highlighter-rouge">TintColor</code>.</p>
<p>Now we can just add the effect to our <code class="language-plaintext highlighter-rouge">TabbedPage</code> and change the tint color for example <code class="language-plaintext highlighter-rouge">OnCurrentPageChanged</code> so each tab will have its own tint color.</p>
<p>Full example can be found on <a href="https://github.com/yuv4ik/XFDynamicSelectedTabTintColor">github</a>.</p>Evgeny ZborovskyAndroidAnatomy of Code snippets in Visual Studio for Mac2018-11-28T00:00:00+00:002018-11-28T00:00:00+00:00http://evgenyzborovsky.com/2018/11/28/anatomy-of-code-snippets-in-visual-studio-for-mac<p>Code snippet is a shortcut that can be used to generate a code from a specific template. Example of a built-in code snippet:</p>
<p>Type <code class="language-plaintext highlighter-rouge">cw</code> and double press the <code class="language-plaintext highlighter-rouge">Tab</code> key will result in <code class="language-plaintext highlighter-rouge">Console.Writeline();</code></p>
<p>Thats a pretty simple example, however we pressed only 4 keys instead of 19 (ignoring the autocompletion of IntelliSense). In more advanced cases it might be a code snippet to generate a <code class="language-plaintext highlighter-rouge">BindableProperty</code> or a simple property in a <code class="language-plaintext highlighter-rouge">ViewModel</code> that should notify the binding engine about updates. Sounds like we can increase our performance by letting the code snippets generate boring repetitive code for us.</p>
<p>Visual Studio for Mac is shipped with a <a href="https://docs.microsoft.com/en-us/visualstudio/ide/visual-csharp-code-snippets?view=vs-2015">default code snippets</a> that can be used as a great example. Let’s take a look on the <code class="language-plaintext highlighter-rouge">cw</code> code snippet. First let’s open the editor by clicking on <code class="language-plaintext highlighter-rouge">Visual Studio</code> > <code class="language-plaintext highlighter-rouge">Preferences</code> > <code class="language-plaintext highlighter-rouge">Text Editor</code> > <code class="language-plaintext highlighter-rouge">Code Snippets</code>. Now select the <code class="language-plaintext highlighter-rouge">cw</code> code snippet under <code class="language-plaintext highlighter-rouge">C#</code> group:</p>
<p><img src="/images/2018-11-28-anatomy-of-code-snippets-in-visual-studio-for-mac/1.png" alt="" /></p>
<p>#1. <code class="language-plaintext highlighter-rouge">Shortcut</code> - is the shortcut we have to type in order to generate the code from the template. In this example it is <code class="language-plaintext highlighter-rouge">cw</code> (Console.WriteLine).<br />
#2. <code class="language-plaintext highlighter-rouge">Group</code> - there are different available groups including F#, Python and Razor.<br />
#3. <code class="language-plaintext highlighter-rouge">Variables</code> - on the screenshot <code class="language-plaintext highlighter-rouge">#3</code> appear twice to demonstrate the definition of the <code class="language-plaintext highlighter-rouge">$SystemConsoleWriteLine$</code> variable and its properties.<br />
#4. <code class="language-plaintext highlighter-rouge">Default</code> - stands for the default value of the variable. Please note that in order to avoid confusion we should also provide a namespace.<br />
#5. <code class="language-plaintext highlighter-rouge">Function</code> - we can apply built-in functions like <code class="language-plaintext highlighter-rouge">GetSimpleTypeName("System#Console.WriteLine")</code>. It will make sure to remove the namespace before <code class="language-plaintext highlighter-rouge">Console.WriteLine</code> if <code class="language-plaintext highlighter-rouge">using System</code> is already in place otherwise it will use the default value (#4). The list of supported functions can be found <a href="https://github.com/mono/monodevelop/blob/master/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/ExpansionObject.cs#L268">here</a>.<br /></p>
<p>The template is just a <code class="language-plaintext highlighter-rouge">XML</code> file that live in <code class="language-plaintext highlighter-rouge">~/Library/VisualStudio/{version}/Snippets</code> directory, which means that you can easily import and export code snippets that you create.</p>
<p>Earlier today I created a <a href="https://github.com/yuv4ik/vsmac_code_snippets">GitHub repository</a> with a couple of handy code snippets for Visual Studio for Mac and especially for Xamarin. You are welcome to check and contribute by sharing your own code snippets!</p>Evgeny ZborovskyCode snippet is a shortcut that can be used to generate a code from a specific template. Example of a built-in code snippet:Notification about an empty ListView in Xamarin.Forms2018-11-12T00:00:00+00:002018-11-12T00:00:00+00:00http://evgenyzborovsky.com/2018/11/12/notification-about-an-empty-listview-in-xamarin-forms<p><img src="/images/2018-11-12-notification-about-an-empty-listview-in-xamarin-forms/1.gif" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">ListView</code> is one of my favourite UI controls available in Xamarin.Forms. It is mostly easy to use and customise. Just bind a collection of data, define the representation of each item and you are done!</p>
<p>However, there is one pitfall which most of the developers tend to ignore - if the bound collection is empty, the <code class="language-plaintext highlighter-rouge">ListView</code> will have nothing to show. Depending on the targeting platform it may look ugly or confusing for the end user.</p>
<p>In this blogpost we will check few possible solutions. One solution will be purely implemented on the <code class="language-plaintext highlighter-rouge">ViewModel</code> level and the other one will be a reusable <code class="language-plaintext highlighter-rouge">ListView</code> control wrapper.</p>
<p>Let’s start with a simple case where you have a single <code class="language-plaintext highlighter-rouge">ListView</code> in the app and a reusable solution may sound like an overkill. In this case we will need to add an empty list indication to the View/Page and swap the <code class="language-plaintext highlighter-rouge">IsVisible</code> property between the <code class="language-plaintext highlighter-rouge">ListView</code> and the indicator when the collection become empty:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"> <span class="p"><</span><span class="n">Label</span>
<span class="err"> </span><span class="n">IsVisible</span><span class="p">=</span><span class="s">"{Binding IsNotEmptyData, Converter={StaticResource invertBooleanConverter}}"</span>
<span class="err"> </span><span class="n">VerticalTextAlignment</span><span class="p">=</span><span class="s">"Center"</span>
<span class="err"> </span><span class="n">HorizontalTextAlignment</span><span class="p">=</span><span class="s">"Center"</span>
<span class="err"> </span><span class="n">FontAttributes</span><span class="p">=</span><span class="s">"Italic"</span>
<span class="err"> </span><span class="n">Text</span><span class="p">=</span><span class="s">"Sorry, it seems that the list is empty."</span><span class="err"> </span><span class="p">/></span>
<span class="p"><</span><span class="n">ListView</span>
<span class="err"> </span><span class="n">IsVisible</span><span class="p">=</span><span class="s">"{Binding IsNotEmptyData}"</span>
<span class="err"> </span><span class="n">ItemsSource</span><span class="p">=</span><span class="s">"{Binding Data}"</span><span class="err"> </span><span class="p">/></span></code></pre></figure>
<p>As you see both <code class="language-plaintext highlighter-rouge">Label</code> and <code class="language-plaintext highlighter-rouge">ListView</code> has the <code class="language-plaintext highlighter-rouge">IsVisible</code> property bound to <code class="language-plaintext highlighter-rouge">IsNotEmptyData</code> property that is defined on the <code class="language-plaintext highlighter-rouge">ViewModel</code> and look like this:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="n">List</span><span class="p"><</span><span class="kt">string</span><span class="p">></span><span class="err"> </span><span class="n">data</span><span class="p">;</span>
<span class="k">public</span><span class="err"> </span><span class="n">List</span><span class="p"><</span><span class="kt">string</span><span class="p">></span><span class="err"> </span><span class="n">Data</span>
<span class="p">{</span>
<span class="err"> </span><span class="k">get</span><span class="err"> </span><span class="p">=></span><span class="err"> </span><span class="n">data</span><span class="p">;</span>
<span class="err"> </span><span class="k">set</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">data</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">value</span><span class="p">;</span>
<span class="err"> </span><span class="nf">RaisePropertyChanged</span><span class="p">();</span>
<span class="err"> </span><span class="nf">RaisePropertyChanged</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">IsNotEmptyData</span><span class="p">));</span>
<span class="err"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span><span class="err"> </span><span class="kt">bool</span><span class="err"> </span><span class="n">IsNotEmptyData</span><span class="err"> </span><span class="p">=></span><span class="err"> </span><span class="n">data</span><span class="err"> </span><span class="p">!=</span><span class="err"> </span><span class="k">null</span><span class="err"> </span><span class="p">&&</span><span class="err"> </span><span class="n">data</span><span class="p">.</span><span class="n">Count</span><span class="err"> </span><span class="p">></span><span class="err"> </span><span class="m">0</span><span class="p">;</span></code></pre></figure>
<p>When <code class="language-plaintext highlighter-rouge">Data</code> property is changing it also raising a change event of the <code class="language-plaintext highlighter-rouge">IsNotEmptyData</code> property. Quite easy, but not reusable with multiple <code class="language-plaintext highlighter-rouge">ListView</code>s in the app.</p>
<p>Second approach I want to demonstrate is a custom control which simply wraps a <code class="language-plaintext highlighter-rouge">ListView</code> control by a <code class="language-plaintext highlighter-rouge">Label</code> and the visibility logic is managed by it. Here is how our XAML will look like using this approach:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><controls:StaticListViewWithEmptyMessage</span>
<span class="err"> </span><span class="na">EmptyMessage=</span><span class="s">"Sorry, it seems that the list is empty."</span><span class="nt">></span>
<span class="nt"><controls:StaticListViewWithEmptyMessage.ListView></span>
<span class="nt"><ListView</span><span class="err"> </span><span class="na">ItemsSource=</span><span class="s">"{Binding Data}"</span><span class="err"> </span><span class="nt">/></span>
<span class="nt"></controls:StaticListViewWithEmptyMessage.ListView></span>
<span class="nt"></controls:StaticListViewWithEmptyMessage></span></code></pre></figure>
<p>The <code class="language-plaintext highlighter-rouge">ListView</code> is still under your full control as it is being defined right here. All you need is to set the <code class="language-plaintext highlighter-rouge">EmptyMessage</code> property and you should be ready to go! Lets take a look on the <code class="language-plaintext highlighter-rouge">StaticListViewWithEmptyMessage</code> control:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span><span class="err"> </span><span class="k">class</span><span class="err"> </span><span class="nc">StaticListViewWithEmptyMessage</span><span class="err"> </span><span class="p">:</span><span class="err"> </span><span class="n">Grid</span>
<span class="p">{</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="n">ListView</span><span class="err"> </span><span class="n">ListView</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="k">get</span><span class="err"> </span><span class="p">{</span><span class="err"> </span><span class="k">return</span><span class="err"> </span><span class="p">(</span><span class="n">ListView</span><span class="p">)</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">ListViewProperty</span><span class="p">);</span><span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">set</span><span class="err"> </span><span class="p">{</span><span class="err"> </span><span class="nf">SetValue</span><span class="p">(</span><span class="n">ListViewProperty</span><span class="p">,</span><span class="err"> </span><span class="k">value</span><span class="p">);</span><span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="k">static</span><span class="err"> </span><span class="k">readonly</span><span class="err"> </span><span class="n">BindableProperty</span><span class="err"> </span><span class="n">ListViewProperty</span><span class="err"> </span><span class="p">=</span>
<span class="err"> </span><span class="n">BindableProperty</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">ListView</span><span class="p">),</span><span class="err"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">ListView</span><span class="p">),</span><span class="err"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">StaticListViewWithEmptyMessage</span><span class="p">),</span><span class="err"> </span><span class="n">propertyChanged</span><span class="p">:</span><span class="err"> </span><span class="n">HandleListViewChanged</span><span class="p">);</span>
<span class="err"> </span><span class="k">static</span><span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">HandleListViewChanged</span><span class="p">(</span><span class="n">BindableObject</span><span class="err"> </span><span class="n">bindable</span><span class="p">,</span><span class="err"> </span><span class="kt">object</span><span class="err"> </span><span class="n">oldValue</span><span class="p">,</span><span class="err"> </span><span class="kt">object</span><span class="err"> </span><span class="n">newValue</span><span class="p">)</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">intelligentListView</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="p">(</span><span class="n">StaticListViewWithEmptyMessage</span><span class="p">)</span><span class="n">bindable</span><span class="p">;</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">oldList</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="p">(</span><span class="n">ListView</span><span class="p">)</span><span class="n">oldValue</span><span class="p">;</span>
<span class="err"> </span><span class="k">if</span><span class="p">(</span><span class="n">oldList</span><span class="err"> </span><span class="p">!=</span><span class="err"> </span><span class="k">null</span><span class="p">)</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">intelligentListView</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="nf">Remove</span><span class="p">(</span><span class="n">oldList</span><span class="p">);</span>
<span class="err"> </span><span class="n">oldList</span><span class="p">.</span><span class="n">PropertyChanged</span><span class="err"> </span><span class="p">-=</span><span class="err"> </span><span class="n">ListViewPropertyChanged</span><span class="p">;</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">newList</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="p">(</span><span class="n">ListView</span><span class="p">)</span><span class="n">newValue</span><span class="p">;</span>
<span class="err"> </span><span class="n">newList</span><span class="p">.</span><span class="n">IsVisible</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">false</span><span class="p">;</span>
<span class="err"> </span><span class="n">newList</span><span class="p">.</span><span class="n">PropertyChanged</span><span class="err"> </span><span class="p">+=</span><span class="err"> </span><span class="n">ListViewPropertyChanged</span><span class="p">;</span>
<span class="err"> </span><span class="n">intelligentListView</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">newList</span><span class="p">);</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">static</span><span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">ListViewPropertyChanged</span><span class="p">(</span><span class="kt">object</span><span class="err"> </span><span class="n">sender</span><span class="p">,</span><span class="err"> </span><span class="n">System</span><span class="p">.</span><span class="n">ComponentModel</span><span class="p">.</span><span class="n">PropertyChangedEventArgs</span><span class="err"> </span><span class="n">e</span><span class="p">)</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="k">if</span><span class="err"> </span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">PropertyName</span><span class="err"> </span><span class="p">!=</span><span class="err"> </span><span class="n">ListView</span><span class="p">.</span><span class="n">ItemsSourceProperty</span><span class="p">.</span><span class="n">PropertyName</span><span class="p">)</span><span class="err"> </span><span class="k">return</span><span class="p">;</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">listView</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="p">(</span><span class="n">ListView</span><span class="p">)</span><span class="n">sender</span><span class="p">;</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">staticListViewWithEmptyMessage</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">listView</span><span class="p">.</span><span class="n">Parent</span><span class="err"> </span><span class="k">as</span><span class="err"> </span><span class="n">StaticListViewWithEmptyMessage</span><span class="p">;</span>
<span class="err"> </span><span class="k">if</span><span class="err"> </span><span class="p">(</span><span class="n">listView</span><span class="p">.</span><span class="n">ItemsSource</span><span class="err"> </span><span class="p">==</span><span class="err"> </span><span class="k">null</span><span class="err"> </span><span class="p">||</span><span class="err"> </span><span class="p">(</span><span class="n">listView</span><span class="p">.</span><span class="n">ItemsSource</span><span class="err"> </span><span class="k">as</span><span class="err"> </span><span class="n">ICollection</span><span class="p">).</span><span class="n">Count</span><span class="err"> </span><span class="p">==</span><span class="err"> </span><span class="m">0</span><span class="p">)</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">listView</span><span class="p">.</span><span class="n">IsVisible</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">false</span><span class="p">;</span>
<span class="err"> </span><span class="n">staticListViewWithEmptyMessage</span><span class="p">.</span><span class="n">emptyMessageLbl</span><span class="p">.</span><span class="n">IsVisible</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">true</span><span class="p">;</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">else</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">listView</span><span class="p">.</span><span class="n">IsVisible</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">true</span><span class="p">;</span>
<span class="err"> </span><span class="n">staticListViewWithEmptyMessage</span><span class="p">.</span><span class="n">emptyMessageLbl</span><span class="p">.</span><span class="n">IsVisible</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">false</span><span class="p">;</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="kt">string</span><span class="err"> </span><span class="n">EmptyMessage</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="k">get</span><span class="err"> </span><span class="p">{</span><span class="err"> </span><span class="k">return</span><span class="err"> </span><span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">EmptyMessageProperty</span><span class="p">);</span><span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">set</span><span class="err"> </span><span class="p">{</span><span class="err"> </span><span class="nf">SetValue</span><span class="p">(</span><span class="n">EmptyMessageProperty</span><span class="p">,</span><span class="err"> </span><span class="k">value</span><span class="p">);</span><span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="k">static</span><span class="err"> </span><span class="k">readonly</span><span class="err"> </span><span class="n">BindableProperty</span><span class="err"> </span><span class="n">EmptyMessageProperty</span><span class="err"> </span><span class="p">=</span>
<span class="err"> </span><span class="n">BindableProperty</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">EmptyMessage</span><span class="p">),</span><span class="err"> </span><span class="k">typeof</span><span class="p">(</span><span class="kt">string</span><span class="p">),</span><span class="err"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">StaticListViewWithEmptyMessage</span><span class="p">));</span>
<span class="err"> </span><span class="k">readonly</span><span class="err"> </span><span class="n">Label</span><span class="err"> </span><span class="n">emptyMessageLbl</span><span class="p">;</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="nf">StaticListViewWithEmptyMessage</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">Children</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">emptyMessageLbl</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="nf">GenerateEmptyLabel</span><span class="p">());</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="n">Label</span><span class="err"> </span><span class="nf">GenerateEmptyLabel</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">lbl</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">new</span><span class="err"> </span><span class="n">Label</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">BindingContext</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="k">this</span><span class="p">,</span><span class="err"> </span>
<span class="err"> </span><span class="n">VerticalTextAlignment</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">TextAlignment</span><span class="p">.</span><span class="n">Center</span><span class="p">,</span>
<span class="err"> </span><span class="n">HorizontalTextAlignment</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">TextAlignment</span><span class="p">.</span><span class="n">Center</span><span class="p">,</span>
<span class="err"> </span><span class="n">FontAttributes</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">FontAttributes</span><span class="p">.</span><span class="n">Italic</span>
<span class="err"> </span><span class="p">};</span>
<span class="err"> </span><span class="n">lbl</span><span class="p">.</span><span class="nf">SetBinding</span><span class="p">(</span><span class="n">Label</span><span class="p">.</span><span class="n">TextProperty</span><span class="p">,</span><span class="err"> </span><span class="n">EmptyMessageProperty</span><span class="p">.</span><span class="n">PropertyName</span><span class="p">);</span>
<span class="err"> </span><span class="k">return</span><span class="err"> </span><span class="n">lbl</span><span class="p">;</span>
<span class="err"> </span><span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>First we define a <code class="language-plaintext highlighter-rouge">BindableProperty</code> of type <code class="language-plaintext highlighter-rouge">ListView</code> that allows us to expose the <code class="language-plaintext highlighter-rouge">ListView</code> fully as demonstrated above. In order to show/hide our <code class="language-plaintext highlighter-rouge">ListView</code> we have to listen and response correctly to related changes.</p>
<p>Please note that both of the examples assumed that the collection bound to the <code class="language-plaintext highlighter-rouge">ListView</code> is a static collection if you want to handle a dynamic collection, you will have to use <code class="language-plaintext highlighter-rouge">ObservableCollection</code> and listen to <code class="language-plaintext highlighter-rouge">CollectionChanged</code> event instead.</p>
<p>The source code is available <a href="https://github.com/yuv4ik/XFEmptyListMessage">here</a>.</p>Evgeny ZborovskyDynamically changing the status bar appearance in Xamarin.Forms2018-08-20T00:00:00+00:002018-08-20T00:00:00+00:00http://evgenyzborovsky.com/2018/08/20/dynamically-changing-the-status-bar-appearance-in-xamarin-forms<p><img src="/images/2018-08-20-dynamically-changing-the-status-bar-appearance-in-xamarin-forms/1.gif" alt="" /></p>
<p>Usually there is a need in changing the status bar appearance to match the application theme at least once. In more advanced cases the appearance of the status bar may change multiple times, due different colour themes on different screens within the application.</p>
<p>Status bar appearance is about it’s background and text colours. Both properties has their own limitations on different platforms, however we could manipulate both with the solution described below.</p>
<p>Our goal is simple, we want to be able to switch the status bar appearance between <code class="language-plaintext highlighter-rouge">LightTheme</code> and <code class="language-plaintext highlighter-rouge">DarkTheme</code> at runtime:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span><span class="err"> </span><span class="k">interface</span><span class="err"> </span><span class="nc">IStatusBarStyleManager</span>
<span class="p">{</span>
<span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">SetLightTheme</span><span class="p">();</span>
<span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">SetDarkTheme</span><span class="p">();</span>
<span class="p">}</span></code></pre></figure>
<h2 id="android">Android</h2>
<h3 id="background-colour">Background colour</h3>
<p><a href="https://developer.android.com/guide/topics/ui/look-and-feel/themes#Versions">Since Android Lollipop (21)</a> it is possible to set a custom status bar background colour by simply defining it in style.xml with a key <code class="language-plaintext highlighter-rouge">colorPrimaryDark</code> or programatically (check below).</p>
<h3 id="text-colour">Text colour</h3>
<p><a href="https://developer.android.com/reference/android/R.attr#windowLightStatusBar">Since Android M (23)</a> it is possible to set a predefined status bar text colour theme to light or dark.</p>
<h3 id="implementation">Implementation</h3>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span><span class="err"> </span><span class="k">class</span><span class="err"> </span><span class="nc">StatusBarStyleManager</span><span class="err"> </span><span class="p">:</span><span class="err"> </span><span class="n">IStatusBarStyleManager</span>
<span class="p">{</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">SetDarkTheme</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="k">if</span><span class="err"> </span><span class="p">(</span><span class="n">Build</span><span class="p">.</span><span class="n">VERSION</span><span class="p">.</span><span class="n">SdkInt</span><span class="err"> </span><span class="p">>=</span><span class="err"> </span><span class="n">BuildVersionCodes</span><span class="p">.</span><span class="n">M</span><span class="p">)</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">Device</span><span class="p">.</span><span class="nf">BeginInvokeOnMainThread</span><span class="p">(()</span><span class="err"> </span><span class="p">=></span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">currentWindow</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="nf">GetCurrentWindow</span><span class="p">();</span>
<span class="err"> </span><span class="n">currentWindow</span><span class="p">.</span><span class="n">DecorView</span><span class="p">.</span><span class="n">SystemUiVisibility</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="m">0</span><span class="p">;</span>
<span class="err"> </span><span class="n">currentWindow</span><span class="p">.</span><span class="nf">SetStatusBarColor</span><span class="p">(</span><span class="n">Android</span><span class="p">.</span><span class="n">Graphics</span><span class="p">.</span><span class="n">Color</span><span class="p">.</span><span class="n">DarkCyan</span><span class="p">);</span>
<span class="err"> </span><span class="p">});</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">SetLightTheme</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="k">if</span><span class="err"> </span><span class="p">(</span><span class="n">Build</span><span class="p">.</span><span class="n">VERSION</span><span class="p">.</span><span class="n">SdkInt</span><span class="err"> </span><span class="p">>=</span><span class="err"> </span><span class="n">BuildVersionCodes</span><span class="p">.</span><span class="n">M</span><span class="p">)</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">Device</span><span class="p">.</span><span class="nf">BeginInvokeOnMainThread</span><span class="p">(()</span><span class="err"> </span><span class="p">=></span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">currentWindow</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="nf">GetCurrentWindow</span><span class="p">();</span>
<span class="err"> </span><span class="n">currentWindow</span><span class="p">.</span><span class="n">DecorView</span><span class="p">.</span><span class="n">SystemUiVisibility</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="p">(</span><span class="n">StatusBarVisibility</span><span class="p">)</span><span class="n">SystemUiFlags</span><span class="p">.</span><span class="n">LightStatusBar</span><span class="p">;</span>
<span class="err"> </span><span class="n">currentWindow</span><span class="p">.</span><span class="nf">SetStatusBarColor</span><span class="p">(</span><span class="n">Android</span><span class="p">.</span><span class="n">Graphics</span><span class="p">.</span><span class="n">Color</span><span class="p">.</span><span class="n">LightGreen</span><span class="p">);</span>
<span class="err"> </span><span class="p">});</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="n">Window</span><span class="err"> </span><span class="nf">GetCurrentWindow</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">window</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">CrossCurrentActivity</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">Activity</span><span class="p">.</span><span class="n">Window</span><span class="p">;</span>
<span class="err"> </span><span class="c1">// clear FLAG_TRANSLUCENT_STATUS flag:</span>
<span class="err"> </span><span class="n">window</span><span class="p">.</span><span class="nf">ClearFlags</span><span class="p">(</span><span class="n">WindowManagerFlags</span><span class="p">.</span><span class="n">TranslucentStatus</span><span class="p">);</span>
<span class="err"> </span><span class="c1">// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window</span>
<span class="err"> </span><span class="n">window</span><span class="p">.</span><span class="nf">AddFlags</span><span class="p">(</span><span class="n">WindowManagerFlags</span><span class="p">.</span><span class="n">DrawsSystemBarBackgrounds</span><span class="p">);</span>
<span class="err"> </span><span class="k">return</span><span class="err"> </span><span class="n">window</span><span class="p">;</span>
<span class="err"> </span><span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Please note that I am using <a href="https://github.com/jamesmontemagno/CurrentActivityPlugin#current-activity-plugin-for-xamarinandroid">Current Activity Plugin for Xamarin.Android</a> in order to get a reference to the current displayed activity.</p>
<h2 id="ios">iOS</h2>
<h3 id="background-colour-1">Background colour</h3>
<p>In iOS the status bar background colour by default matching the colour of the navigation bar. In other words, we don’t have to explicitly set the background colour of the status bar if we want it to match the background colour of the navigation bar.</p>
<h3 id="text-colour-1">Text colour</h3>
<p><a href="https://developer.apple.com/documentation/uikit/uiapplication/1622923-setstatusbarstyle">Since iOS 7</a> it is possible to set a predefined status bar text colour theme to light or dark. However, we will have to manipulate the <code class="language-plaintext highlighter-rouge">Info.plist</code>. Since status bar behaviour is determined by view controllers by default, we have to disable this:</p>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false />
<p>Next, we can define a default <a href="https://developer.apple.com/documentation/uikit/uistatusbarstyle">text colour theme</a>:</p>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<h3 id="implementation-1">Implementation</h3>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span><span class="err"> </span><span class="k">class</span><span class="err"> </span><span class="nc">StatusBarStyleManager</span><span class="err"> </span><span class="p">:</span><span class="err"> </span><span class="n">IStatusBarStyleManager</span>
<span class="p">{</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">SetDarkTheme</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">Device</span><span class="p">.</span><span class="nf">BeginInvokeOnMainThread</span><span class="p">(()</span><span class="err"> </span><span class="p">=></span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">UIApplication</span><span class="p">.</span><span class="n">SharedApplication</span><span class="p">.</span><span class="nf">SetStatusBarStyle</span><span class="p">(</span><span class="n">UIStatusBarStyle</span><span class="p">.</span><span class="n">LightContent</span><span class="p">,</span><span class="err"> </span><span class="k">false</span><span class="p">);</span>
<span class="err"> </span><span class="nf">GetCurrentViewController</span><span class="p">().</span><span class="nf">SetNeedsStatusBarAppearanceUpdate</span><span class="p">();</span>
<span class="err"> </span><span class="p">});</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="k">public</span><span class="err"> </span><span class="k">void</span><span class="err"> </span><span class="nf">SetLightTheme</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">Device</span><span class="p">.</span><span class="nf">BeginInvokeOnMainThread</span><span class="p">(()</span><span class="err"> </span><span class="p">=></span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="n">UIApplication</span><span class="p">.</span><span class="n">SharedApplication</span><span class="p">.</span><span class="nf">SetStatusBarStyle</span><span class="p">(</span><span class="n">UIStatusBarStyle</span><span class="p">.</span><span class="n">Default</span><span class="p">,</span><span class="err"> </span><span class="k">false</span><span class="p">);</span>
<span class="err"> </span><span class="nf">GetCurrentViewController</span><span class="p">().</span><span class="nf">SetNeedsStatusBarAppearanceUpdate</span><span class="p">();</span>
<span class="err"> </span><span class="p">});</span>
<span class="err"> </span><span class="p">}</span>
<span class="err"> </span><span class="n">UIViewController</span><span class="err"> </span><span class="nf">GetCurrentViewController</span><span class="p">()</span>
<span class="err"> </span><span class="p">{</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">window</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">UIApplication</span><span class="p">.</span><span class="n">SharedApplication</span><span class="p">.</span><span class="n">KeyWindow</span><span class="p">;</span>
<span class="err"> </span><span class="kt">var</span><span class="err"> </span><span class="n">vc</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">window</span><span class="p">.</span><span class="n">RootViewController</span><span class="p">;</span>
<span class="err"> </span><span class="k">while</span><span class="err"> </span><span class="p">(</span><span class="n">vc</span><span class="p">.</span><span class="n">PresentedViewController</span><span class="err"> </span><span class="p">!=</span><span class="err"> </span><span class="k">null</span><span class="p">)</span>
<span class="err"> </span><span class="n">vc</span><span class="err"> </span><span class="p">=</span><span class="err"> </span><span class="n">vc</span><span class="p">.</span><span class="n">PresentedViewController</span><span class="p">;</span>
<span class="err"> </span><span class="k">return</span><span class="err"> </span><span class="n">vc</span><span class="p">;</span>
<span class="err"> </span><span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<h2 id="conclusion">Conclusion</h2>
<p>At first this topic may seem very confusing, especially on Android, however it turned out to be very simple and easily achievable as you can se above. The code can be found on <a href="https://github.com/yuv4ik/XFDynamicStatusBarAppearance">github</a>.</p>Evgeny ZborovskyRetrieving Facebook User Access Token in Xamarin.Forms2018-08-08T00:00:00+00:002018-08-08T00:00:00+00:00http://evgenyzborovsky.com/2018/08/08/retrieving-facebook-user-access-token-in-xamarin-forms<p>Few months ago I wrote an article about <a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">Using Native Facebook Login Button in Xamarin.Formsicle</a> where I explained how to retrieve user access token using Facebook SDK. It is still a valid read and a good solution, however, recently I discovered that there is a shorter way to achieve almost the same thing.</p>
<p>In this article we will learn how to retrieve Facebook user access token, using a custom button (not native) with just a few lines of code. I assume that you know how to create a Facebook application and configure your Android and iOS projects. If I am mistaken please refer to <a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">my previous article</a>.</p>
<p>There is an open source project <a href="https://github.com/CrossGeeks/FacebookClientPlugin">Facebook Client Plugin</a> that allow you to login, share and query Facebook using static API. It has a good documentation and good well known developers behind it. As you may already understand we are going to use it to retrieve user access token from Facebook in our project.</p>
<p>Here is the recipe:</p>
<ol>
<li>Create and configure Facebook app (more info <a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">here</a> or <a href="https://github.com/CrossGeeks/FacebookClientPlugin/blob/master/docs/FacebookPortalSetup.md">here</a>).</li>
<li>Add <code class="language-plaintext highlighter-rouge">Plugin.FacebookClient</code> NuGet package to .NET Standard and platform targeting projects.</li>
<li>Configure platform targeting projects (more info <a href="/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/">here</a> or <a href="https://github.com/CrossGeeks/FacebookClientPlugin">here</a>).</li>
<li>Add a custom Facebook login button to your Page/View.</li>
<li>Bind a command to the previously created button with the next code:</li>
</ol>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="kt">var</span> <span class="n">fbLoginResponse</span><span class="p">=</span>
<span class="n">awaitCrossFacebookClient</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="nf">LoginAsync</span><span class="p">(</span><span class="n">newstring</span><span class="p">[]{</span><span class="err">“</span><span class="n">email</span><span class="err">”</span><span class="p">});</span>
<span class="k">if</span><span class="p">(</span><span class="n">fbLoginResponse</span><span class="p">.</span><span class="n">Status</span> <span class="p">==</span> <span class="n">FacebookActionStatus</span><span class="p">.</span><span class="n">Completed</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">fbUserAccessToken</span><span class="p">=</span><span class="n">CrossFacebookClient</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">ActiveToken</span><span class="p">;</span>
<span class="c1">// TODO: Use the fb access token</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="c1">// Something went wrong</span>
<span class="p">}</span></code></pre></figure>
<p>That should be it!</p>
<p>You could create a wrapper interface and class to make this code testable, to be able to inject it as a dependency and to adjust it to your needs. This solution might be less configurable, however, the integration is very easy and the amount of code is miserable compare to the previous solution.</p>
<p>Big thanks to <a href="https://github.com/CrossGeeks">CrossGeeks</a>!</p>Evgeny ZborovskyFew months ago I wrote an article about Using Native Facebook Login Button in Xamarin.Formsicle where I explained how to retrieve user access token using Facebook SDK. It is still a valid read and a good solution, however, recently I discovered that there is a shorter way to achieve almost the same thing.Repeater or Bindable StackLayout2018-06-06T00:00:00+00:002018-06-06T00:00:00+00:00http://evgenyzborovsky.com/2018/06/06/repeater-or-bindable-stacklayout<table>
<tbody>
<tr>
<td>iOS</td>
<td>Android</td>
</tr>
<tr>
<td><img src="/images/2018-06-06-repeater-or-bindable-stacklayout/1.png" alt="" /></td>
<td><img src="/images/2018-06-06-repeater-or-bindable-stacklayout/2.png" alt="" /></td>
</tr>
</tbody>
</table>
<h2 id="intro">Intro</h2>
<p>When designing a View (Page) we need to take into consideration that there might be a lot of content to show. Typically we should use a <code class="language-plaintext highlighter-rouge">ListView</code>, which by default is scrollable. However, what if you have to show more than one <code class="language-plaintext highlighter-rouge">ListView</code> on a single page? Nesting <code class="language-plaintext highlighter-rouge">ScrollViews</code> is a very bad practice that should be avoided unless natively supported. In this case it will most probably make sense to put all the content within a single <code class="language-plaintext highlighter-rouge">ScrollView</code>. But how? Here is where the <code class="language-plaintext highlighter-rouge">Repeater</code> or <code class="language-plaintext highlighter-rouge">BindableStackLayout</code> comes into play.</p>
<h2 id="custom-control">Custom Control</h2>
<p>In order to solve the problem described in the Intro, we will have to extend a <code class="language-plaintext highlighter-rouge">StackLayout</code> and expose the next bindable properties:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">ItemsSource</code> - Gets/sets the source of items to template and display.</li>
<li><code class="language-plaintext highlighter-rouge">ItemDataTemplate</code> - Gets/sets the item template.</li>
<li><code class="language-plaintext highlighter-rouge">Title</code> - Gets/sets the header/title of the control.</li>
</ul>
<p>The implementation is very simple and does not require any custom renderers since we are simply going to reuse a layout that arranges child views vertically or horizontally. We are going to use <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/bindable-properties">BindableProperties</a> in order to be able to react to value changes in a real time.</p>
<p>Here is a very simple implementation in ±50 lines of code:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">BindableStackLayout</span> <span class="p">:</span> <span class="n">StackLayout</span>
<span class="p">{</span>
<span class="k">readonly</span> <span class="n">Label</span> <span class="n">header</span><span class="p">;</span>
<span class="k">public</span> <span class="nf">BindableStackLayout</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">header</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Label</span><span class="p">();</span>
<span class="n">Children</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">header</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">IEnumerable</span> <span class="n">ItemsSource</span>
<span class="p">{</span>
<span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">IEnumerable</span><span class="p">)</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">ItemsSourceProperty</span><span class="p">);</span> <span class="p">}</span>
<span class="k">set</span> <span class="p">{</span> <span class="nf">SetValue</span><span class="p">(</span><span class="n">ItemsSourceProperty</span><span class="p">,</span> <span class="k">value</span><span class="p">);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">readonly</span> <span class="n">BindableProperty</span> <span class="n">ItemsSourceProperty</span> <span class="p">=</span>
<span class="n">BindableProperty</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">ItemsSource</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="n">IEnumerable</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="n">BindableStackLayout</span><span class="p">),</span>
<span class="n">propertyChanged</span><span class="p">:</span> <span class="p">(</span><span class="n">bindable</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">newValue</span><span class="p">)</span> <span class="p">=></span> <span class="p">((</span><span class="n">BindableStackLayout</span><span class="p">)</span><span class="n">bindable</span><span class="p">).</span><span class="nf">PopulateItems</span><span class="p">());</span>
<span class="k">public</span> <span class="n">DataTemplate</span> <span class="n">ItemDataTemplate</span>
<span class="p">{</span>
<span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">DataTemplate</span><span class="p">)</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">ItemDataTemplateProperty</span><span class="p">);</span> <span class="p">}</span>
<span class="k">set</span> <span class="p">{</span> <span class="nf">SetValue</span><span class="p">(</span><span class="n">ItemDataTemplateProperty</span><span class="p">,</span> <span class="k">value</span><span class="p">);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">readonly</span> <span class="n">BindableProperty</span> <span class="n">ItemDataTemplateProperty</span> <span class="p">=</span>
<span class="n">BindableProperty</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">ItemDataTemplate</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="n">DataTemplate</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="n">BindableStackLayout</span><span class="p">));</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Title</span>
<span class="p">{</span>
<span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="kt">string</span><span class="p">)</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">TitleProperty</span><span class="p">);</span> <span class="p">}</span>
<span class="k">set</span> <span class="p">{</span> <span class="nf">SetValue</span><span class="p">(</span><span class="n">TitleProperty</span><span class="p">,</span> <span class="k">value</span><span class="p">);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">readonly</span> <span class="n">BindableProperty</span> <span class="n">TitleProperty</span> <span class="p">=</span>
<span class="n">BindableProperty</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="k">nameof</span><span class="p">(</span><span class="n">Title</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="kt">string</span><span class="p">),</span> <span class="k">typeof</span><span class="p">(</span><span class="n">BindableStackLayout</span><span class="p">),</span>
<span class="n">propertyChanged</span><span class="p">:</span> <span class="p">(</span><span class="n">bindable</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">newValue</span><span class="p">)</span> <span class="p">=></span> <span class="p">((</span><span class="n">BindableStackLayout</span><span class="p">)</span><span class="n">bindable</span><span class="p">).</span><span class="nf">PopulateHeader</span><span class="p">());</span>
<span class="k">void</span> <span class="nf">PopulateItems</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ItemsSource</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">item</span> <span class="k">in</span> <span class="n">ItemsSource</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">itemTemplate</span> <span class="p">=</span> <span class="n">ItemDataTemplate</span><span class="p">.</span><span class="nf">CreateContent</span><span class="p">()</span> <span class="k">as</span> <span class="n">View</span><span class="p">;</span>
<span class="n">itemTemplate</span><span class="p">.</span><span class="n">BindingContext</span> <span class="p">=</span> <span class="n">item</span><span class="p">;</span>
<span class="n">Children</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">itemTemplate</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">void</span> <span class="nf">PopulateHeader</span><span class="p">()</span> <span class="p">=></span> <span class="n">header</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="n">Title</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>All the “stuff” is happening within the <code class="language-plaintext highlighter-rouge">PopulateItems</code> method which is called when a value of <code class="language-plaintext highlighter-rouge">ItemSource</code> property is changing. We simply iterate through the collection of items and add them as children to the root view. Please note that each child is represented by <code class="language-plaintext highlighter-rouge">ItemDataTemplate</code>, so all we have to do, is to invoke <code class="language-plaintext highlighter-rouge">CreateContent</code> method that will be generate the view for us.</p>
<p>Usage example:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">sealed</span> <span class="k">class</span> <span class="nc">MyColor</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">HexCode</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="nf">MyColor</span><span class="p">(</span><span class="kt">string</span> <span class="n">name</span><span class="p">,</span> <span class="kt">string</span> <span class="n">hexCode</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Name</span> <span class="p">=</span> <span class="n">name</span><span class="p">;</span>
<span class="n">HexCode</span> <span class="p">=</span> <span class="n">hexCode</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">MainViewModel</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">IReadOnlyCollection</span><span class="p"><</span><span class="n">MyColor</span><span class="p">></span> <span class="n">MyColors</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">MyColor</span><span class="p">></span>
<span class="p">{</span>
<span class="k">new</span> <span class="nf">MyColor</span><span class="p">(</span><span class="err">“</span><span class="n">Black</span><span class="err">”</span><span class="p">,</span> <span class="err">“#</span><span class="m">000000</span><span class="err">”</span><span class="p">),</span>
<span class="k">new</span> <span class="nf">MyColor</span><span class="p">(</span><span class="err">“</span><span class="n">Hot</span> <span class="n">Pink</span><span class="err">”</span><span class="p">,</span> <span class="err">“#</span><span class="n">ff69b4</span><span class="err">”</span><span class="p">),</span>
<span class="k">new</span> <span class="nf">MyColor</span><span class="p">(</span><span class="err">“</span><span class="n">Red</span><span class="err">”</span><span class="p">,</span> <span class="err">“#</span><span class="n">ff0000</span><span class="err">”</span><span class="p">),</span>
<span class="k">new</span> <span class="nf">MyColor</span><span class="p">(</span><span class="err">“</span><span class="n">Sort</span> <span class="n">of</span> <span class="n">Green</span><span class="err">”</span><span class="p">,</span> <span class="err">“#</span><span class="m">7</span><span class="n">cff00</span><span class="err">”</span><span class="p">)</span>
<span class="p">};</span>
<span class="p">}</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp"><?xml version=“1.0“ encoding=“utf-8“?></span>
<span class="nt"><ContentPage</span>
<span class="na">xmlns=</span><span class="s">“http://xamarin.com/schemas/2014/forms“</span>
<span class="na">xmlns:x=</span><span class="s">“http://schemas.microsoft.com/winfx/2009/xaml“</span>
<span class="na">xmlns:local=</span><span class="s">“clr-namespace:XFBindableStackLayout“</span>
<span class="na">x:Class=</span><span class="s">“XFBindableStackLayout.MainPage“</span><span class="nt">></span>
<span class="nt"><ContentPage.BindingContext></span>
<span class="nt"><local:MainViewModel</span> <span class="nt">/></span>
<span class="nt"></ContentPage.BindingContext></span>
<span class="nt"><local:BindableStackLayout</span>
<span class="na">Title=</span><span class="s">“Colors:“</span>
<span class="na">ItemsSource=</span><span class="s">“{Binding</span> <span class="err">MyColors}“</span>
<span class="na">VerticalOptions=</span><span class="s">“Center“</span>
<span class="na">HorizontalOptions=</span><span class="s">“Center“</span><span class="nt">></span>
<span class="nt"><local:BindableStackLayout.ItemDataTemplate></span>
<span class="nt"><DataTemplate></span>
<span class="nt"><StackLayout</span>
<span class="na">Orientation=</span><span class="s">“Horizontal“</span><span class="nt">></span>
<span class="nt"><BoxView</span>
<span class="na">WidthRequest=</span><span class="s">“50“</span>
<span class="na">HeightRequest=</span><span class="s">“50“</span>
<span class="na">Color=</span><span class="s">“{Binding</span> <span class="err">HexCode}“</span> <span class="nt">/></span>
<span class="nt"><Label</span>
<span class="na">Text=</span><span class="s">“{Binding</span> <span class="err">Name}“</span>
<span class="na">VerticalTextAlignment=</span><span class="s">“Center“</span> <span class="nt">/></span>
<span class="nt"></StackLayout></span>
<span class="nt"></DataTemplate></span>
<span class="nt"></local:BindableStackLayout.ItemDataTemplate></span>
<span class="nt"></local:BindableStackLayout></span>
<span class="nt"></ContentPage></span></code></pre></figure>
<h2 id="conclusion">Conclusion</h2>
<p>The implementation above is very simple, however some corner cases are not handled on purpose. This can be a nice homework for you to discover and handle those. The code above is fully available on <a href="https://github.com/yuv4ik/XFBindableStackLayout">github</a>.</p>
<p>Good luck!</p>Evgeny ZborovskyiOS AndroidXamarin.Forms Recipe: Label with Letter Spacing2018-05-29T00:00:00+00:002018-05-29T00:00:00+00:00http://evgenyzborovsky.com/2018/05/29/xamarin-forms-recipe-label-with-letter-spacing<table>
<tbody>
<tr>
<td>iOS</td>
<td>Android</td>
</tr>
<tr>
<td><img src="/images/2018-05-29-xamarin-forms-recipe-label-with-letter-spacing/1.png" alt="" /></td>
<td><img src="/images/2018-05-29-xamarin-forms-recipe-label-with-letter-spacing/2.png" alt="" /></td>
</tr>
</tbody>
</table>
<p>Setting a letter spacing for a <code class="language-plaintext highlighter-rouge">Label</code> in Android and iOS turned into an interesting research for me. I would expect that such a common task would be easily done with a help of a <code class="language-plaintext highlighter-rouge">Renderer</code> or an <code class="language-plaintext highlighter-rouge">Effect</code>. However, I was very surprised to discover that some platforms do not have a built-in support for setting letter spacing.</p>
<h2 id="android">Android</h2>
<p>It turned out that setting letter spacing it is not possible on pre Lollipop (< 21) without hacks when on Lollipop+ there is a dedicated method: <a href="https://developer.android.com/reference/android/widget/TextView.html#setLetterSpacing(float)">setLetterSpacing()</a>. Luckily <a href="https://stackoverflow.com/a/16429758/1970317">this SO post</a> offered a creative solution:</p>
<blockquote>
<p>.. method adds a space between each letter of the String and with <a href="http://developer.android.com/reference/android/text/SpannedString.html">SpannedString</a> changes the TextScaleX of the spaces, allowing positive and negative spacing ..</p>
</blockquote>
<p>The math in this solution is a bit weird and should be adjusted according to your specific needs. Otherwise it is doing it’s job nicely.</p>
<p>Checking the <a href="https://developer.android.com/about/dashboards/">Distribution dashboard</a>, it seems that 15.3% of users are using KitKat or older and 84.7% are using Lollipop or newer Android version. So hopefully very soon this recipe could be simplified🤞.</p>
<h2 id="ios">iOS</h2>
<p>On iOS it is (as expected) a one-liner using <a href="https://developer.apple.com/documentation/uikit/uilabel/1620542-attributedtext">attributedText</a> property.</p>
<h2 id="the-recipe">The recipe</h2>
<p>I combined the details described above into <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/effects/introduction">Effect</a>:</p>
<script src="https://gist.github.com/bf1bd8a82d1880f53825baf69d9fa1fe.js"> </script>Evgeny ZborovskyiOS AndroidImmutable Models in MVVM2018-05-16T00:00:00+00:002018-05-16T00:00:00+00:00http://evgenyzborovsky.com/2018/05/16/immutable-models-in-mvvm<p><img src="/images/2018-05-16-immutable-models-in-mvvm/1.jpg" alt="" /></p>
<h6 id="source-flickr-jeff-attaway">Source: flickr/ Jeff Attaway</h6>
<h2 id="mvvm"><span style="color:red">M</span>VVM</h2>
<p>The first <code class="language-plaintext highlighter-rouge">M</code> stands for Model - an implementation of the application’s domain model that includes a data model along with business and validation logic. Examples of model objects include repositories, business objects, data transfer objects (DTOs), Plain Old CLR Objects (POCOs), and generated entity and proxy objects.</p>
<p><a href="https://msdn.microsoft.com/en-us/library/hh848246.aspx?f=255&MSPPError=-2147217396">definition source</a></p>
<h2 id="immutability">Immutability</h2>
<p>In object-oriented and functional programming, an immutable object(unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created.</p>
<p><a href="https://en.wikipedia.org/wiki/Immutable_object">definition source</a></p>
<h2 id="why-bother">Why bother?</h2>
<p>Imagine the next simple situation, your application downloads a JSON, deserialises it to an object and then presents the downloaded data. You would expect the downloaded data to be one-to-one to the data on the remote server, however the data can be accidentally or intentionally mutated.</p>
<p>Here is an example of a mutable <code class="language-plaintext highlighter-rouge">Model</code>:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">MyMutableObject</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">long</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Title</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">List</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="n">Contents</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>All the properties has public setters which means that any of those can be changed after the object creation. Even if we make all the setters private, it could be still possible to manipulate data within the <code class="language-plaintext highlighter-rouge">List</code>.</p>
<p>Here is an example of immutable <code class="language-plaintext highlighter-rouge">Model</code>:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="k">public</span> <span class="k">sealed</span> <span class="k">class</span> <span class="nc">MyImmutableObject</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">long</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Title</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">IReadOnlyCollection</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="n">Contents</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="nf">MyImmutableObject</span><span class="p">(</span>
<span class="kt">long</span> <span class="n">id</span><span class="p">,</span>
<span class="kt">string</span> <span class="n">title</span><span class="p">,</span>
<span class="n">IReadOnlyCollection</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="n">contents</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Id</span> <span class="p">=</span> <span class="n">id</span><span class="p">;</span>
<span class="n">Title</span> <span class="p">=</span> <span class="n">title</span><span class="p">;</span>
<span class="n">Contents</span> <span class="p">=</span> <span class="n">contents</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>There are no public setters available and mutable collection type is replaced by “immutable” one. There is no option to extend this class as well as changing the data after the object is created.</p>
<blockquote>
<p>Note: IReadOnlyCollection is not a real immutable collection but an immutable facade. It is not thread safe and possible to cast to IList and try to manipulate the collection, however System.NotSupportedException will be thrown.</p>
</blockquote>
<p>Alternatively we can add a <code class="language-plaintext highlighter-rouge">System.Collections.Immutable</code> NuGet package and replace <code class="language-plaintext highlighter-rouge">IReadOnlyCollection<T></code> by <code class="language-plaintext highlighter-rouge">IImmutableList<T></code> if we want a real immutable collection.</p>
<h2 id="json-deserialization">JSON Deserialization</h2>
<p>Often <code class="language-plaintext highlighter-rouge">Models</code> used for deserialization and it can be tricky to deserialize JSON to immutable object. Luckily with <a href="https://github.com/JamesNK/Newtonsoft.Json">Json.NET</a> it is not an issue. We can easily serialize and deserialize <code class="language-plaintext highlighter-rouge">MyImmutableObject</code>:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="kt">var</span> <span class="n">myImmutableObject</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MyImmutableObject</span><span class="p">(</span>
<span class="n">id</span><span class="p">:</span> <span class="m">1</span><span class="p">,</span>
<span class="n">title</span><span class="p">:</span> <span class="err">“</span><span class="n">Test</span><span class="err">”</span><span class="p">,</span>
<span class="n">contents</span><span class="p">:</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="p">{</span> <span class="err">“</span><span class="n">One</span><span class="err">”</span><span class="p">,</span> <span class="err">“</span><span class="n">Two</span><span class="err">”</span><span class="p">,</span> <span class="err">“</span><span class="n">Three</span><span class="err">”</span> <span class="p">});</span>
<span class="kt">var</span> <span class="n">json</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="nf">SerializeObject</span><span class="p">(</span><span class="n">myImmutableObject</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">deserializedObject</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="n">DeserializeObject</span><span class="p"><</span><span class="n">MyImmutableObject</span><span class="p">>(</span><span class="n">json</span><span class="p">);</span></code></pre></figure>
<p>Please note that if your <code class="language-plaintext highlighter-rouge">Model</code> has more than one constructor you will need to mark one for deserialization explicitly, by adding a <code class="language-plaintext highlighter-rouge">JsonConstructor</code> <a href="http://james.newtonking.com/projects/json/help/html/T_Newtonsoft_Json_JsonConstructorAttribute.htm">attribute</a>.</p>
<h2 id="orm">ORM</h2>
<p>With .NET Standard we can use EntityFramework Core in our Xamarin.Forms applications which is great! And it is great twice since we can have a code first immutable model fully supported by EF.</p>
<p>Example:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">[</span><span class="nf">Table</span><span class="p">(</span><span class="err">“</span><span class="n">ToDo</span><span class="err">”</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">sealed</span> <span class="k">class</span> <span class="nc">ToDoModel</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">Key</span><span class="p">]</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Title</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Notes</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTimeOffset</span> <span class="n">CreatedAt</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTimeOffset</span><span class="p">?</span> <span class="n">UpdatedAt</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="nf">ToDoModel</span><span class="p">()</span> <span class="p">{</span> <span class="cm">/* EF requires a parameterless constructor. */</span> <span class="p">}</span>
<span class="k">public</span> <span class="nf">ToDoModel</span><span class="p">(</span>
<span class="kt">int</span> <span class="n">id</span><span class="p">,</span>
<span class="kt">string</span> <span class="n">title</span><span class="p">,</span>
<span class="kt">string</span> <span class="n">notes</span><span class="p">,</span>
<span class="n">DateTimeOffset</span> <span class="n">createdAt</span><span class="p">,</span>
<span class="n">DateTimeOffset</span><span class="p">?</span> <span class="n">updatedAt</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Id</span> <span class="p">=</span> <span class="n">id</span><span class="p">;</span>
<span class="n">Title</span> <span class="p">=</span> <span class="n">title</span><span class="p">;</span>
<span class="n">Notes</span> <span class="p">=</span> <span class="n">notes</span><span class="p">;</span>
<span class="n">CreatedAt</span> <span class="p">=</span> <span class="n">createdAt</span><span class="p">;</span>
<span class="n">UpdatedAt</span> <span class="p">=</span> <span class="n">updatedAt</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>When using an “immutable” <code class="language-plaintext highlighter-rouge">Model</code> with EF keep in mind:</p>
<ul>
<li>Parameterless constructor - is required, should be private.</li>
<li>Setters - are required, should private.</li>
<li>Object tracking - should be disabled.</li>
</ul>
<blockquote>
<p>Notes:</p>
<ul>
<li><a href="https://www.nuget.org/packages/sqlite-net-pcl/">SQLite.NET</a> did not work properly with private constructor and setters.</li>
<li>We have to count with private setters since it is still possible to change a value with a private setter within the same class.</li>
</ul>
</blockquote>
<h2 id="conclusion">Conclusion</h2>
<p>In this blogpost we discussed how to make immutable <code class="language-plaintext highlighter-rouge">Models</code> and checked few common scenarios. I would recommend to start immutable and change to mutable if necessary. Here are few recommendations to keep in mind:</p>
<ul>
<li>Forget about private setters: prop -> propg</li>
<li>Make publicly available properties readonly</li>
<li>Use constructors</li>
<li>Seal classes</li>
<li>Use <a href="https://www.nuget.org/packages/System.Collections.Immutable/">immutable collections</a> or at least <code class="language-plaintext highlighter-rouge">[IReadOnlyCollection<T>](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlycollection-1?view=netstandard-2.0)</code></li>
<li>The goal is not to get 100% immutability but to improve code quality</li>
</ul>
<p>Immutability is a very interesting topic which has pros and cons. For example it may harm performance or introduce unnecessary complexity in some cases, so use it wisely. There are few great resources that I would recommend to get familiar with:</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/ericlippert/2007/11/13/immutability-in-c-part-one-kinds-of-immutability/">Immutability in C# Part One: Kinds of Immutability</a> by Eric Lippert</li>
<li><a href="https://msdn.microsoft.com/en-us/magazine/mt795189.aspx?f=255&MSPPError=-2147217396">.NET Framework - Immutable Collections</a> by Hadi Brais</li>
<li><a href="https://www.youtube.com/watch?v=O89-zG84QK4">The changing state of immutability C#</a> by Jon Skeet (video)</li>
</ul>Evgeny ZborovskySource: flickr/ Jeff Attaway