Creating Reusable XAML User Controls with Xamarin Forms
In the previous post on making fancy layouts with Xamarin Forms we saw how you can design a Dashboard style application that stretches to fill any device size. However one of the challenges of the particular design we chose for Falafel 2 Go was the need to support the concept of an Image Button, where both the icon and the text work as a single control to launch an activity.
Xamarin Forms does provide an ImageCell control, which can be used in a TableView to render both text and image as a single control. However, this control is laid out horizontally with the text positioned on the right side of the image as you would expect for a list of items.

While we could likely acheive a more precise layout with a custom renderer, we found a much more elegnat, and more importantly, reusable option by instead creating a User Control.
XAML User Controls
The concept of User Controls is not new, and exists in many different platforms including Silverlight, XAML for Windows and Windows Phone as well as Web Forms. Basically the idea is to create a small container for a collection of controls that will be reused as a single control throughout the application. The User Control exposes properties allowing you to reuse the control while allowing each instance of the control to have different settings, layout, or behavior.
Because User Controls are so useful (and simple to create) on other platforms, we were pleased and relieved to discover that Xamarin Forms supports them as well. While we weren’t able to find any documentation on the matter, with some experimentation we discovered the solution below. If there are official docs for this, please let me know in the comments so I can link to them!
Creating the Xamarin Forms User Control
Begin by adding a regular Xamarin Forms XAML Control to the project. By default this creates a ContentPage. For our layout, we want the image and text to flow vertically, so it makes sense to use a StackLayout, which is why we named the control StackLayoutButton. We can then change the XAML so that the control is also a StackLayout, as shown in the complete example later in the post.
In addition, the code-behind class by default doesn’t inherit from any base class. Usually you would modify this to be a ContentPage to both match the XAML definition as well as expose the properties and methods of the base control. However, because we’re using a StackLayout, we simply needed to update this to inherit from that control. This is also shown later in the full code-behind snippet.
By changing the class of the control we can proceed to add additional XAML controls to the StackLayout to make up the overall User Control. In this case we’re adding both the Image and Label controls as shown in the complete code below, completing the self-contained StackLayoutButton. Notice that we can define the properties for each control so that they are global to all instances of the button, eliminating the need to set them over and over for each one.
But what if we want to vary the properties on a specific control?
Accessing Child Controls and Properties
Because the individual controls are defined inside the StackLayout, we don’t have direct access to them from the User Control when we add them to the main page. However, we can workaround this by adding get and set properties to the StackLayoutButton which expose either the individual properties of a control, or the entire control itself.
If you review the full code of the StackLayoutButton code-behind below, you see that we’ve created two additional public properties. The TextColor sets or returns the value of the Label property so it can be set at the UserControl level. The other Label control returns the actual Label itself, so that we could potentially access and modify any property of that control.
This is demonstrated in the code-behind for the ActivitesPage control, where we access an instance of the StackLayoutButton by name, and can then access theTextControl property to set the BackgroundColor of that control.
Here’s what the final example page looks like. We’ve combined the two options to change both the Font color and the BackgroundColor using the exposed properties for specific buttons.

At last, here are the complete code samples for the controls, starting with the XAML for the StackLayoutButton:
<StackLayout xmlns=“http://xamarin.com/schemas/2014/forms”
xmlns:common=“clr-namespace:Falafel2GoV2.Common;assembly=Falafel2GoV2”
xmlns:x=“http://schemas.microsoft.com/winfx/2009/xaml”
x:Class=“Falafel2GoV2.Controls.StackLayoutButton“>
<Image x:Name=“Icon” Source=“{Binding Icon}” />
<Label x:Name=“Text” Text=“{Binding Title}” HorizontalOptions=“Center” LineBreakMode=“NoWrap” Font=“Small” TextColor=“{x:Static common:ColorResources.ListTitle}” />
</StackLayout>
The StackLayoutButton code-behind:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;namespace Falafel2GoV2.Controls
{
public partial class StackLayoutButton : StackLayout
{
public Color TextColor
{
get { return this.Text.TextColor; }
set { this.Text.TextColor = value; }
}public Label TextControl
{
get { return this.Text; }
set { this.Text = value; }
}public StackLayoutButton()
{
InitializeComponent();
}
}
}
The ActivitiesView XAML:
<ContentPage xmlns=“http://xamarin.com/schemas/2014/forms”
xmlns:x=“http://schemas.microsoft.com/winfx/2009/xaml”
xmlns:common=“clr-namespace:Falafel2GoV2.Common;assembly=Falafel2GoV2”
xmlns:controls=“clr-namespace:Falafel2GoV2.Controls;assembly=Falafel2GoV2”
x:Class=“Falafel2GoV2.Views.ActivitiesPage”
Title=“{Binding ViewName}”
BackgroundImage=“mainBack.png“>
<ContentPage.Content>
<StackLayout Orientation=“Vertical” Padding=“{x:Static common:PaddingResources.MainBody}“>
<Label Text=“{Binding ViewName}” Font=“42” IsVisible=“{Binding IsWindowsPhone}” />
<ActivityIndicator IsRunning=“{Binding IsLoading}” IsVisible=“{Binding IsLoading}” Color=“{x:Static common:ColorResources.ActivityIndicator}” /><Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=“*” />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height=“3*” />
<RowDefinition Height=“4*” />
</Grid.RowDefinitions><Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=“*” />
<ColumnDefinition Width=“*” />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height=“*” />
</Grid.RowDefinitions><controls:StackLayoutButton BindingContext=“{Binding Blog}” TextColor=“Blue” /><controls:StackLayoutButton x:Name=“RedButton”Grid.Column=“1” BindingContext=“{Binding Training}” TextColor=“Red” />
</Grid><
Grid Grid.Row=“1“>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=“*” />
<ColumnDefinition Width=“*” />
<ColumnDefinition Width=“*” />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height=“*” />
<RowDefinition Height=“*” />
</Grid.RowDefinitions><
controls:StackLayoutButton BindingContext=“{Binding Facebook}” />
<controls:StackLayoutButton Grid.Column=“1” BindingContext=“{Binding Twitter}” />
<controls:StackLayoutButton Grid.Column=“2” BindingContext=“{Binding Google}” /><
controls:StackLayoutButton Grid.Row=“1” BindingContext=“{Binding Eventboard}” />
<controls:StackLayoutButton Grid.Row=“1” Grid.Column=“1” BindingContext=“{Binding Website}” />
<controls:StackLayoutButton Grid.Row=“1” Grid.Column=“2” BindingContext=“{Binding Contact}” />
</Grid>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>
And finally the ActivitiesView code-behind:
using System.Collections.Generic;
using Falafel2GoV2;
using Falafel2GoV2.Views;
using Xamarin.Forms;
using Falafel2GoV2.ViewModels;
using Falafel2GoV2.Controls;
using Falafel2GoV2.Models;namespace Falafel2GoV2.Views
{
public partial class ActivitiesPage : ContentPage
{private ActivitiesViewModel vm;public ActivitiesPage()
{
InitializeComponent();
vm = new ActivitiesViewModel();
this.BindingContext = vm;RedButton.TextControl.BackgroundColor =Color.Black;
}}
}
Wrapping Up and Next Steps
By creating a User Control we were able to eliminate the need to define several copies of controls, encapsulating the controls into a single container so it can be defined with a single line a code. In addition, because we added properties to the control, we allow each instance of the control to have its own properties, and even behaviors.
The only thing left is to allow the user to Tap this new custom button to launch the activity. We’ll see how easy this is to do in the next post.
Until then, as always, I hope this was helpful!
from:http://blog.falafel.com/creating-reusable-xaml-user-controls-xamarin-forms/
Creating Reusable XAML User Controls with Xamarin Forms的更多相关文章
- Xamarin.Forms移动开发系列4 :XAML基础
摘要 本文介绍Xamarin.Forms创建用户界面的语言:XAML基础部分. 前言 本文介绍Xamarin.Forms定义用户界面的语言:XAML. 本篇篇幅较长,主要讲述XAML语法,以及对其他基 ...
- Xamarin.Forms之XAML
官网参考 XAML基础知识 XAML(eXtensible Application Markup Language)可扩展应用程序标记语言,允许开发者在Xamarin.Forms应用中采用标记而不是代 ...
- Xamarin.Forms 开发资源集合(复制)
复制:https://www.cnblogs.com/mschen/p/10199997.html 收集整理了下 Xamarin.Forms 的学习参考资料,分享给大家,稍后会不断补充: UI样式 S ...
- Xamarin.Forms 开发资源集合
收集整理了下 Xamarin.Forms 的学习参考资料,分享给大家,稍后会不断补充: UI样式 Snppts: Xamarin Forms UI Snippets. Prebuilt Templat ...
- Xamarin.Forms介绍
On May 28, 2014, Xamarin introduced Xamarin.Forms, which allows you to write user-interface code tha ...
- Xamarin.Forms 简介
An Introduction to Xamarin.Forms 来源:http://developer.xamarin.com/guides/cross-platform/xamarin-forms ...
- Add AI feature to Xamarin.Forms app
Now, AI is one of important technologies.Almost all platforms have API sets of AI. Following list is ...
- 在 Xamarin.Forms 实现密码输入EntryCell
在 Xamarin.Forms 中,我们通常使用 TableView 来构建输入表单.Xamarin 为我们提供了 EntryCell 用于输入文本,但是其并不支持密码输入,即密码掩码.这里要对 En ...
- Xamarin.Forms 自定义控件(呈现器和效果)
Xamarin.Forms 使用目标平台的本机控件呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留了相应的界面外观.凭借效果,无需进行自定义呈现器实现,即可自定义每个平台上的本 ...
随机推荐
- 使用eclipse为Servlet在Tomcat中的部署方法
一:下载安装jdk,tomcat,eclipse: 使用eclipse建立动态web项目lcj,更改编译文件目录,方法如下: 右键点击→工程名称→属性(Properties)或(Building Pa ...
- Go语言之Windows 10开发工具LiteIDE初步使用
Intel Core i5-8250U,Windows 10家庭中文版,go version go1.11 windows/amd64,LiteIDE X34.1 在RUNOOB.COM的Go语言教程 ...
- Python_oldboy_自动化运维之路_线程,进程,协程(十一)
本节内容: 线程 进程 协程 IO多路复用 自定义异步非阻塞的框架 线程和进程的介绍: 举个例子,拿甄嬛传举列线程和进程的关系: 总结:1.工作最小单元是线程,进程说白了就是提供资源的 2.一个应用程 ...
- vue组件库(一):前期准备工作
前言 将近期项目内自行开发一个vue组件,做个总结,记录下自己的思维过程~~~ 正文 接到这个任务后,还是要做些准备工作的. 主要内容如下: 1.优化下所在团队前端开发流程 服务器搭建gitlab,采 ...
- 结合IdentityServer4配置Ocelot的Json配置文件管理更新
Ocelot提供了AddAdministration方法来设置配置路由以及授权方式 services.AddOcelot().AddAdministration("/admin", ...
- k8s中新建一个namespace和harborsecret的yaml文件
注意哟, 不同的harborsecret,在不同的namespace中,是不共用的. 也就是说,如果在default名字空间中,创建了一个docker login secret, 在其它名字空间中,是 ...
- 【LOJ】#2491. 「BJOI2018」求和
题解 对于50个k都维护一个\(i^k\)前缀和即可 查询的时候就是查询一段连续的区间和,再加上根节点的 代码 #include <bits/stdc++.h> #define fi fi ...
- 使用IDEA搭建spring
从前使用eclipse开发,集成jar包,现在使用maven来管理 一: 1.框架 2.pom 需要spring core与spring context. <?xml version=" ...
- [USACO08FEB]修路Making the Grade
[USACO08FEB]修路Making the Grade比较难的dp,比赛时打的找LIS,然后其他的尽可能靠近,40分.先举个例子61 2 3 1 4 561 2 3 3 4 5第4个1要么改成3 ...
- NLP自然语言处理系列5-支持向量机(SVM)
1.什么是支持向量机 支持向量机(Support Vector Machine,SVM)是一种经典的分类模型,在早期的文档分类等领域有一定的应用.了解SVM的推导过程是一个充满乐趣和挑战的过程,耐心的 ...