D-loader's Codebloghttp://d-loader.dk/
Code adventures in .NETArticulate, blogging built on Umbraco1064http://d-loader.dk/archive/using-styles-in-xamarinforms/
.NETXamarinUsing styles in Xamarin.Forms<p>Styles are used to group a set of property settings, which can be applied to visual elements in a view. A style works very much the same way as a class in CSS, and is a great way to avoid duplicated code by using references instead of hard coded values. In this article I will show you how to work with style tags, and how to apply them to elements. Style support was added to Xamarin.Forms 1.3.0.</p>
<h2>Xamarin.Forms 1.3.0 Pre-release</h2>
<p>At the time of writing, Xamarin.Forms version 1.3.0 is in pre-release. You can download the Nu-Get packaged needed to follow this example from <a href="http://cdn.vanillaforums.com/xamarin.vanillaforums.com/FileUpload/81/5aecd7bf2b7a6ddc9a3aa99e2cd84c.zip">here</a>. You will need to drop the binding to the version of Xamarin.Forms you are currently using, and retarget all of your projects to use the Xamarin.Forms 1.3.0 pre-release assembly:</p>
<p><img style="width: 500px; height:252.53549695740367px;" src="http://d-loader.dk/media/1020/xamarin130nuget.png?width=500&amp;height=252.53549695740367" alt="Xamarin 1.3 NuGet" rel="1074" /></p>
<p>At this point in time, the final syntax for style support has not been fully decided. This article is based on the 1.3.0 pre-release, so please be aware that the syntax might change in later versions.</p>
<h2>Styles</h2>
<p>In order to make a style, we first have to create a view with a set of controls that we can apply our styles to. For this example, I have set up a <strong>ContentPage</strong> with a <strong>StackLayout </strong>containing two <strong>Label</strong> elements:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinTests.Views.StylesTestpage"&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Label Text="Header" /&gt;
&lt;Label Text="Bodytext value" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;</pre>
<p>First we have to create a container to hold our styles. For this we will need a <strong>ResourceDictionary</strong> at the root level of the page. By defining our <strong>ResourceDictionary</strong> at the root level, we will be able to access our styles from all of our elements on the page. We define our <strong>ResourceDictionary</strong> in the <strong>Resources</strong> property of the <strong>ContentPage</strong> element:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinTests.Views.StylesTestpage"&gt;
&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Label Text="Header" /&gt;
&lt;Label Text="Bodytext value" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;</pre>
<p> </p>
<p>Now that we have our container, we are ready to add some styles. We do that by defining a <strong>Style </strong>element inside of our <strong>ResourceDictionary</strong>. For this demo, we will add a style for the header and a style for the bodytext:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinTests.Views.StylesTestpage"&gt;
&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;Style x:Key="blueTextHeadline" TargetType="Label"&gt;
&lt;Setter Property="Label.TextColor" Value="Blue" /&gt;
&lt;Setter Property="Label.HorizontalOptions" Value="Center" /&gt;
&lt;Setter Property="Label.FontSize" Value="30" /&gt;
&lt;/Style&gt;
&lt;Style x:Key="bodyText" TargetType="Label"&gt;
&lt;Setter Property="Label.TextColor" Value="Red" /&gt;
&lt;/Style&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Label Text="Header" /&gt;
&lt;Label Text="Bodytext value" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;</pre>
<p> </p>
<p>You might be wondering why we have to specify the full path to the property we want to modify inside the <strong>Setter</strong> element in our <strong>Style</strong> tag, since we have already defined that our style should target <strong>Label</strong> elements. This is a requirement in the pre-release version of the Xamarin.Forms 1.3.0 and is subject to change. Besides this, the <strong>Setter </strong>elements are used in the same way as they are used in the Microsoft ecosystem. If we test the app now, we get the following:</p>
<p><img style="width: 300.7518796992481px; height:500px;" src="http://d-loader.dk/media/1016/toplevelstylesnotapplied.png?width=300.7518796992481&amp;height=500" alt="Top level styles not applied" rel="1069" /></p>
<p>We have not yet defined the link between our <strong>Label</strong> elements and the style we want to apply. To do this, we will add a static reference to the element we want to style using the standard <strong>StaticResource</strong> syntax:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinTests.Views.StylesTestpage"&gt;
&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;Style x:Key="blueTextHeadline" TargetType="Label"&gt;
&lt;Setter Property="Label.TextColor" Value="Blue" /&gt;
&lt;Setter Property="Label.HorizontalOptions" Value="Center" /&gt;
&lt;Setter Property="Label.FontSize" Value="30" /&gt;
&lt;/Style&gt;
&lt;Style x:Key="bodyText" TargetType="Label"&gt;
&lt;Setter Property="Label.TextColor" Value="Red" /&gt;
&lt;/Style&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Label Text="Header" Style="{StaticResource blueTextHeadline}" /&gt;
&lt;Label Text="Bodytext value" Style="{StaticResource bodyText}" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;</pre>
<p> </p>
<p>If we test the app again, we get the following:</p>
<p><img style="width: 299.7496871088861px; height:500px;" src="http://d-loader.dk/media/1013/toplevelbothstylesapplied.png?width=299.7496871088861&amp;height=500" alt="Top level styles applied" rel="1066" /></p>
<h2>Inherited styles</h2>
<p>It is also possible to inherit from other styles, to avoid repeated code. This is done by linking the <strong>BasedOn</strong> property on a style to the style you want to use as the base style using a <strong>StaticResource </strong>reference. We can change to code to make a new style, <strong>inheritedTextStyle</strong>, which will use the <strong>bodyText</strong> style as its base style:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamarinTests.Views.StylesTestpage"&gt;
&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;Style x:Key="blueTextHeadline" TargetType="Label"&gt;
&lt;Setter Property="Label.TextColor" Value="Blue" /&gt;
&lt;Setter Property="Label.HorizontalOptions" Value="Center" /&gt;
&lt;Setter Property="Label.FontSize" Value="30" /&gt;
&lt;/Style&gt;
&lt;Style x:Key="bodyText" TargetType="Label"&gt;
&lt;Setter Property="Label.TextColor" Value="Red" /&gt;
&lt;/Style&gt;
&lt;Style x:Key="interitedTextStyle" TargetType="Label" BasedOn="{StaticResource bodyText}"&gt;
&lt;Setter Property="Label.FontSize" Value="40" /&gt;
&lt;/Style&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Label Text="Header" Style="{StaticResource blueTextHeadline}" /&gt;
&lt;Label Text="Bodytext value" Style="{StaticResource interitedTextStyle}" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;</pre>
<p> </p>
<p>If we test the app again, we get the following:</p>
<p><img style="width: 301.75658720200755px; height:500px;" src="http://d-loader.dk/media/1015/toplevelstylesandinheritedstyleapplied.png?width=301.75658720200755&amp;height=500" alt="Top level style and intrited style applied" rel="1067" /></p>
<h2>Global level styles</h2>
<p>At this point, it is not possible to link a <strong>ResourceDictionary</strong> residing in a XAML file outside of a specific page, like it is the Microsoft XAML implementation. The only way to create global level styles at the time of writing is to add a <strong>ResourceDictionary</strong> to the <strong>Resources</strong> member of the <strong>App</strong> entry point class like so:</p>
<pre>using Xamarin.Forms;
using XamarinTests.Views;
namespace XamarinTests
{
public class App : Application
{
public App ()
{
MainPage = new StylesTestpage ();
Resources = new ResourceDictionary (); //Global level ResourceDictionary
}
}
}
</pre>
<p> </p>
<p>The problem with this approach is, that we can only make one <strong>ResourceDictionary</strong>, and not break our styling into multiple files. Also, we cannot define our styles in XAML using this approach. The Xamarin team is aware of this issue, and hopefully it will be fixed for the final release of 1.3.0.</p>Wed, 22 Oct 2014 12:30:00 +02002014-10-22T12:30:00+02:001084http://d-loader.dk/archive/using-behaviors-in-xamarinforms/
.NETXamarinUsing behaviors in Xamarin.Forms<p>Behaviors are used to encapsulate logic, which can be attached to a specific component. This logic can be used to make the component behave in a specific way, for instance make a log entry every time a certain event is fired, or rearrange child entities. Support for behaviors were added to Xamarin.Forms version 1.3.0.</p>
<h2>Xamarin.Forms 1.3.0 Pre-release</h2>
<p>At the time of writing, Xamarin.Forms version 1.3.0 is in pre-release. You can download the Nu-Get packaged needed to follow this example from <a href="http://cdn.vanillaforums.com/xamarin.vanillaforums.com/FileUpload/81/5aecd7bf2b7a6ddc9a3aa99e2cd84c.zip">here</a>. You will need to drop the binding to the version of Xamarin.Forms you are currently using, and retarget all of your projects to use the Xamarin.Forms 1.3.0 pre-release assembly:</p>
<p><img style="width: 500px; height:252.53549695740367px;" src="http://d-loader.dk/media/1020/xamarin130nuget.png?width=500&amp;height=252.53549695740367" alt="Xamarin 1.3 NuGet" rel="1074" /></p>
<h2>Behaviors</h2>
<p>In order to make a behavior, we will create a new class which will inherit from <strong>Behavior&lt;T&gt;</strong>:</p>
<pre>using System;
using Xamarin.Forms;
namespace XamarinTests.Behaviors
{
public class ChangeColorButtonBehavior : Behavior&lt;Button&gt;
{
protected override void OnAttachedTo (Button bindable)
{
bindable.Clicked += ButtonClicked;
base.OnAttachedTo (bindable);
}
protected override void OnDetachingFrom (Button bindable)
{
bindable.Clicked -= ButtonClicked;
base.OnDetachingFrom (bindable);
}
private void ButtonClicked(object sender, EventArgs e)
{
var button = sender as Button;
button.BackgroundColor = button.BackgroundColor != Color.Blue ? Color.Blue : Color.Red;
}
}
}</pre>
<p>The way behaviors are implemented in Xamarin.Forms is slightly different from the way it is implemented by Microsoft in their ecosystem. First of all, we do not have access to the <strong>AssociatedObject</strong> member in our class. Instead, the associated object is injected in the relevant overrides instead. From here we can subscribe to all relevant events, and perform as usual. In this example, I am flipping the background color of a button every time it is clicked. It might not be the most exciting example, but it is sufficient to demonstrate concept of behaviors.</p>
<h2>Adding behaviors to elements</h2>
<p>Now that our behavior implementation is done, it is time to add it to a <strong>Button </strong>element:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behaviors="clr-namespace:XamarinTests.Behaviors;assembly=XamarinTests"
x:Class="XamarinTests.BehaviorTestpage"&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Button Text="Click to chance color!"&gt;
&lt;Button.Behaviors&gt;
&lt;behaviors:ChangeColorButtonBehavior /&gt;
&lt;/Button.Behaviors&gt;
&lt;/Button&gt;
&lt;Button Text="Click to do nothing!" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;</pre>
<p>This piece of XAML also shows a key difference between the way behaviors are implemented in Xamarin.Forms. Here it is not necessary to import a special namespace to handle behaviors, as every element inheriting from <strong>VisualElement </strong>contains an <strong>IList&lt;Behavior&gt; </strong>member. To access the <strong>ChangeColorButtonBehavior </strong>created earlier in this example, we import the namespace in which it resides using the standard <strong>clr-namespace </strong>import syntax. We then add the behavior to the first <strong>Button </strong>element, and now we are ready to test the behavior:</p>
<p><img style="width: 300.28735632183907px; height:500px;" src="http://d-loader.dk/media/1017/buttonclickblack.png?width=300.28735632183907&amp;height=500" alt="Button click black" rel="1071" /></p>
<p>When the view is loaded for the first time, both of the <strong>Button </strong>elements will contain their standard background color. If we click both of the <strong>Button</strong> elements now, we will get the following:</p>
<p><img style="width: 300.28735632183907px; height:500px;" src="http://d-loader.dk/media/1018/buttonclickblue.png?width=300.28735632183907&amp;height=500" alt="Button click blue" rel="1072" /></p>
<p>Here we can see the behavior attached to the first button in action. The background color of the first <strong>Button</strong> element is now blue. The second <strong>Button</strong> remains unaffected by the behavior, as it is not attached to that element. By clicking both of the Button elements again, we get the following:</p>
<p><img style="width: 300.28735632183907px; height:500px;" src="http://d-loader.dk/media/1019/buttonclickred.png?width=300.28735632183907&amp;height=500" alt="Button click red" rel="1073" /></p>
<p>Once again the background color of the second <strong>Button </strong>element remains unchanged, while the background color of the first <strong>Button</strong> element has been changed to red. By repeating this pattern we will see the color of the first <strong>Button </strong>element flip between blue and red.</p>Tue, 21 Oct 2014 17:30:00 +02002014-10-21T17:30:00+02:001085http://d-loader.dk/archive/xaml-localization-with-xamarinforms/
.NETXamarinXAML localization with Xamarin.Forms<p>Adding support for multiple languages in Xamarin.Forms is a relatively simple task. If you're using XAML to build your UI however, the solution might not be so obvious however. This is mainly because the XAML parser for Xamarin.Forms isn't as mature as implementation offered by Microsoft, and for that reason it does not offer a solution out of the box for binding translated text directly to your controls. For that reason, we have to hook into the pipeline in order to inject translated text into our controls.</p>
<h2>Resource Files</h2>
<p>If you're coming from a Microsoft based XAML world, you're probably used to working with resource files (*.resx). These files provide a simple way of managing translated values for different languages. Coupled with the <a href="http://dev.windows.com/en-us/develop/multilingual-app-toolkit" target="_blank">Multilingual App Toolkit</a> you easily translate your application into multiple languages. The goal is therefore to create a set of resource files, and hook them into our Xamarin.Forms application.</p>
<h2>Generating Resource Files</h2>
<p>In order to generate our resource files, we'll open up our solution in Visual Studio. The reason for this, is that Visual Studio generate some boilerplate code for us when we generate our first resource file.</p>
<p>For this example, I'm using a PCL Xamarin.Forms project:</p>
<p><img style="width: 353px; height:280px;" src="http://d-loader.dk/media/1026/projectlayout.png?width=353&amp;height=280" alt="Project layout" rel="1081" /> </p>
<p>We'll place our resource files in the project containing our UI. In this example, the views live in the <strong>Glider_Log</strong> project. Create a folder, <strong>Resources</strong>, in this project. Create a resource file in this folder:</p>
<p> <img style="width: 500px; height:274.72527472527474px;" src="http://d-loader.dk/media/1021/createresourcefile.png?width=500&amp;height=274.72527472527474" alt="Create resource file" rel="1076" /></p>
<p>This resource file will be your default language file. I usually put english text in this. If a user loads up your application on a device with a language setting you do not provide translations for, this is the file the application will use. For each language you're going to support, you will need to add an aditional resource file with the name: "Resource.{culture name}.resx". You can find a list of culture names <a href="http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx" target="_blank">here</a>. In this example, I'll add support for Danish. The project now looks like this:</p>
<p> <img style="width: 215px; height:113px;" src="http://d-loader.dk/media/1024/languages.png?width=215&amp;height=113" alt="Languages" rel="1078" /></p>
<p>We'll now add some values to our resource file. I usually use the convention "<strong>view</strong>_<strong>value</strong>", but the only requirement is to use a value with no spaces:</p>
<p><img style="width: 500px; height:134.3042071197411px;" src="http://d-loader.dk/media/1023/englishvalues.png?width=500&amp;height=134.3042071197411" alt="English values" rel="1079" /></p>
<p>Since we're placing the resource files in the same assembly as the views, we can keep the default access modifier of Internal. If you need to reference the values in other assemblies, remember to change the access modifier for each resource file. Now we'll add the translated values to the <strong>Resource.da-DK.resx </strong>file:</p>
<p> <img style="width: 500px; height:130.4px;" src="http://d-loader.dk/media/1022/danishvalues.png?width=500&amp;height=130.4" alt="Danish values" rel="1077" /></p>
<h2>Adding The Glue</h2>
<p>At this point we need to add the glue that allows the engine to inject our values into our controls. For this we'll need to implement the <a href="http://iosapi.xamarin.com/index.aspx?link=T%3AXamarin.Forms.Xaml.IMarkupExtension" target="_blank">IMarkupExtension</a> interface. For this we'll add a new file, <strong>TranslateExtension.cs</strong>, to our <strong>Resources</strong> folder. In this file, we'll implement the interface:</p>
<pre>using System;
using System.Globalization;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Glider_Log.Resources
{
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
public string Text { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
return null;
return Resource.ResourceManager.GetString(Text, CultureInfo.CurrentCulture);
}
}
}
</pre>
<p>This allows us to look up translated values at runtime using the <strong>ResourceManager</strong> (this is part of the boilerplate code generated by Visual Studio earlier. You can examine the code by opening the code-behind file of the <strong>Resource.resx</strong> file ). The resource manager will select the appropriate resource file, depending on the language used on the device. The text value to be translated will be provided by the XAML view.</p>
<p>Next, we'll create a Xamarin.Forms <strong>ContentPage </strong>( Dashboard.xaml ) with a few controls:</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Glider_Log.Dashboard"
xmlns:resources="clr-namespace:Glider_Log.Resources;assembly=Glider_Log"&gt;
&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;LayoutOptions x:Key="horizontalOptions"
Alignment="Center" /&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;ContentPage.Content&gt;
&lt;StackLayout&gt;
&lt;Label Text="{resources:Translate Dashboard_Title}" HorizontalOptions="{StaticResource horizontalOptions}" /&gt;
&lt;Button Text="{resources:Translate Dashboard_New}" /&gt;
&lt;Button Text="{resources:Translate Dashboard_Browse}" /&gt;
&lt;Button Text="{resources:Translate Dashboard_Settings}" /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;
</pre>
<p>First we define the <strong>resources</strong> namespace at the <strong>ContentPage</strong> level. This will allow us to easily reference the <strong>Translate</strong> extension later on. We add a simple StackLayout with 4 controls: One <strong>Label</strong> instance, and three <strong>Button</strong> instances. On each control we'll bind the <strong>Text</strong> property to the translate extension (tip: you can leave out the Extension part of the type name). The value provided will be used by the <strong>ResourceManager</strong> to look up the value to be returned. For this reason, the value provided must be identical to the value in the resource files.</p>
<p>At this point, we're ready to test the application. If we load up the application on a device using English we get the following:</p>
<p> <img style="width: 231px; height:384px;" src="http://d-loader.dk/media/1027/wpenglish.png?width=231&amp;height=384" alt="Windows phone english" rel="1082" /></p>
<p>If we switch the language to Danish, we'll get the following result:</p>
<p><img style="width: 231px; height:384px;" src="http://d-loader.dk/media/1025/wpdanish.png?width=231&amp;height=384" alt="Windows phone danish" rel="1080" /></p>
<p>At this point we have a fully localized application in two languages, working across Android, IOS and Windows Phone, using a centralized solution. Adding support for more languages at this point, is easily achieved by adding more resource files.</p>
<h2>Gotcha</h2>
<p> In order for languages to work on Windows Phone, you have to add support for the specific language first. This is easily done by accessing the projects settings ( <strong>Right-Click</strong> on the project -&gt; <strong>Settings </strong>). From here, you can add the languages you support in the <strong>Supported Cultures</strong> section: </p>
<p><img style="width: 500px; height:277.8372591006424px;" src="http://d-loader.dk/media/1028/wpsupportedlanguages.png?width=500&amp;height=277.8372591006424" alt="Windows phone supported languages" rel="1083" /></p>Mon, 22 Sep 2014 17:33:00 +02002014-09-22T17:33:00+02:00