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/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2015-07-08 苹果企业开发者账号申请记录
2012-07-08 双人游戏下载 双人合作过关游戏 COOP模式 单机游戏 下载大全【分类列表】