Xamarin.Forms FlexLayout 布局扩展+ 模板扩展+弹性换行
Binding a FlexLayout to a Collection
In May we published a doc on the new FlexLayout control that’s present in Xamarin.Forms 3.0. FlexLayout is a versatile layout control that can arrange its children horizontally and vertically in a stack, and is also capable of wrapping its children if there are too many to fit in a single row or column. It also has options for orientation, alignment, and adapting to various screen sizes.
In the FlexLayout guide we outlined some common usage scenarios, with one being a catalog of items that are displayed horizontally, which are navigated through by swiping in the appropriate direction. Each item in the catalog is defined inline in XAML as children of the FlexLayout element. This is all very well for static catalog items that are defined by the developer, but what if the data is stored in a collection that’s populated from an external source such as a web service, or a database? This would require the FlexLayout to bind to a collection containing the data. However, this isn’t currently possible as there’s no ItemsSourceproperty (or similar) on the FlexLayout class.
The purpose of this blog post is to demonstrate extending the FlexLayout with ItemsSource and ItemTemplate properties, so that it can bind to data stored in a collection. Note that the implementation will be a minimally viable implementation, rather than a production ready implementation. It demonstrates the simplest approach for binding a FlexLayout to a collection of items.
The sample the code in this blog post comes from can be found on GitHub.
Extending FlexLayout
The first step is to create a new class that inherits from FlexLayout, and add the required bindable properties and properties:
public class ExtendedFlexLayout : FlexLayout
{
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
nameof(ItemsSource),
typeof(IEnumerable),
typeof(ExtendedFlexLayout),
propertyChanged: OnItemsSourceChanged);
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(
nameof(ItemTemplate),
typeof(DataTemplate),
typeof(ExtendedFlexLayout)); public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
} public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
...
}
The code above simply defines ItemsSource and ItemTemplate properties, along with matching BindableProperty versions of them. The ItemTemplateproperty will reference the DataTemplate to apply to each item in the collection referenced by the ItemsSource property. Note that the ItemsSourcePropertyhas a property changed handler defined, named OnItemsSourceChanged. This is where the templated items will be added to the ExtendedFlexLayout:
public class ExtendedFlexLayout : FlexLayout
{
...
static void OnItemsSourceChanged(BindableObject bindable, object oldVal, object newVal)
{
IEnumerable newValue = newVal as IEnumerable;
var layout = (ExtendedFlexLayout)bindable; layout.Children.Clear();
if (newValue != null)
{
foreach (var item in newValue)
{
layout.Children.Add(layout.CreateChildView(item));
}
}
} View CreateChildView(object item)
{
ItemTemplate.SetValue(BindableObject.BindingContextProperty, item);
return (View)ItemTemplate.CreateContent();
}
}
The OnItemsSourceChanged method iterates through the collection referenced by the ItemsSource property, and calls the CreateChildView method for each item. This method sets the binding context of the ItemTemplate to the item, loads the DataTemplate referenced by the ItemTemplate property, and returns it to the OnItemsSourceChanged method, where the templated item is added as a child of the ExtendedFlexLayout.
Consuming the ExtendedFlexLayout
The ExtendedFlexLayout can be consumed in XAML as follows:
<ScrollView Orientation="Horizontal" Margin="0,20">
<local:ExtendedFlexLayout ItemsSource="{Binding Monkeys}">
<local:ExtendedFlexLayout.ItemTemplate>
<DataTemplate>
<Frame WidthRequest="300"
HeightRequest="480">
<FlexLayout Direction="Column">
<Label Text="{Binding Name}"
Style="{StaticResource headerLabel}" />
<Label Text="{Binding Description}" />
<Label Text="{Binding Trait1}" Margin="10,0,0,0" />
<Label Text="{Binding Trait2}" Margin="10,0,0,0" />
<Label Text="{Binding Trait3}" Margin="10,0,0,0" />
<Image Source="{Binding Image,
Converter={StaticResource _stringToImageConverter}}"
WidthRequest="180"
HeightRequest="180" />
<Label FlexLayout.Grow="1" />
<Button />
</FlexLayout>
</Frame>
</DataTemplate>
</local:ExtendedFlexLayout.ItemTemplate>
</local:ExtendedFlexLayout>
</ScrollView>
This ExtendedFlexLayout instance sets its ItemsSource property to a collection named Monkeys, which exists on the view model the page binds to. It also sets its ItemTemplate property to an inline DataTemplate that binds different views to different properties of each Monkey in the Monkeys collection. The result is, as per the FlexLayout guide, there are three items displayed that can be navigated through by swiping in the appropriate direction:
The difference between the FlexLayout guide and this approach is that in the guide each item is declared inline in XAML. Here, each item comes from a collection that the ExtendedFlexLayout binds to. The advantage of this approach is that it allows the displayed data to be populated from an external source, such as a web service or a database.
Issues
As I previously mentioned, the ExtendedFlexLayout is a minimally viable implementation. While it works for the scenario outlined here, it’s quite limited:
- It doesn’t respond to the bound collection changing at runtime (think ObservableCollection). Instead, the entire collection must be available when binding occurs.
- It doesn’t respond to binding context changes. The binding context must be set when binding occurs, and can’t change.
- It only permits a single defined DataTemplate to be used. It doesn’t allow a DataTemplateSelector to choose a DataTemplate at runtime based on the value of a bound property.
- There’s no UI virtualisation. For large collections, the ExtendedFlexLayout could consume a lot of memory.
I’ll explore some of these issues in future blog posts.
Summary
This blog post has explained how to extend the FlexLayout with ItemsSource and ItemTemplate properties, so that it can bind to data stored in a collection. However, the ExtendedFlexLayout is currently a minimally viable implementation. My next blog post will look at extending the implementation with additional functionality.
The sample this code comes from can be found on GitHub.
Xamarin.Forms FlexLayout 布局扩展+ 模板扩展+弹性换行的更多相关文章
- Xamarin.Forms 界面布局
<!--margin表示控件相对StackLayout的位置是设置组件之间的距离,或者距离父组件边缘的距离, 他的四个值是左边距,上边距,右边距,下边距 --> <!- ...
- Xamarin.Forms移动开发系列5 :XAML标记扩展
摘要 本文主要讲述Xamarin.Forms中XAML的标记扩展. 前言 在Xamarin.Forms移动开发系列4 :XAML基础一文中提到过XAML标记扩展,本文将对标记扩展进行更深入的了解. 大 ...
- 搞懂Xamarin.Forms布局,看这篇应该就够了吧
Xamarin.Forms 布局介绍 什么是布局?可以简单的理解为,我们通过将布局元素有效的组织起来,让屏幕变成我们想要的样子! 我们通过画图的方式来描述一下Xamarin.Forms的布局. 小节锚 ...
- xamarin forms常用的布局StackLayout详解
通过这篇文章你将了解到xamarin forms中最简单常用的布局StackLayout.至于其他几种布局使用起来,效果相对较差,目前在项目中使用最多的也就是这两种布局StackLayout和Grid ...
- Xamarin.Forms——尺寸大小(五 Dealing with sizes)
如之前所见的大量可视化元素均有自己的尺寸大小: iOS的状态栏高度为20,所以我们需要调整iOS的页面的Padding值,留出这个高度. BoxView设置它的默认宽度和高度为40. Frame的默认 ...
- 菜鸟的Xamarin.Forms前行之路——按钮的按下抬起事件的监控(可扩展至其他事件)
提问:监控按钮的点击事件,可以通过按钮的Click事件,或者Command绑定,那么如何监控按钮的按下与抬起,或者移动,长按,双击等事件? 解决方法:各个平台自定义渲染依赖注入. 共享项目PCL: 1 ...
- 菜鸟的Xamarin.Forms前行之路——实现按钮的字体图标(可扩展)
在实际的APP中,带有图标的按钮用到地方还是蛮多的,字体图标往往能更快更生动的传达信息,并且相对于背景图片,字体图标也有着绝对的优势,所以实现按钮的字体图标是值得尝试的. 实现方法:各平台自定义渲染按 ...
- 使用MvvmCross框架实现Xamarin.Forms的汉堡菜单布局
注:本文是英文写的,偷懒自动翻译过来了,原文地址:Implementing MasterDetail layout in Xamarin.Forms by MvvmCross 欢迎大家关注我的公众号: ...
- VS自定义项目模板:[2]创建VSIX项目模板扩展
VS自定义项目模板:[2]创建VSIX项目模板扩展 听语音 | 浏览:1237 | 更新:2015-01-02 09:21 | 标签:软件开发 1 2 3 4 5 6 7 分步阅读 一键约师傅 百度师 ...
随机推荐
- Linux安装Tomcat-Nginx-FastDFS-Redis-Solr-集群——【第九集-补充-之安装iptables】
1,安装完了jdk,tomcat,启动tomcat的bin/startup.sh后,发现在浏览器输入公网ip地址和tomcat的默认(server.xml)中的端口port:8080,无法访问,这主要 ...
- php接入支付宝的流程(转载)
php接入支付宝的流程写在这里供像我一样的小白参考. 1.首先要有一个创建一个应用(选好自己想要的功能,关于支付的功能,貌似都需要签约) 2.下载SDK&Dome(网址https://doc. ...
- EsayUi中常用的属性和方法总结
文章转载自http://www.jb51.net/article/26077.htm 详细了解请查看官方文档 属性分为CSS片段和JS片段 CSS类定义:1.div easyui-window ...
- Python: 你不知道的 super
https://segmentfault.com/a/1190000007426467 Python: 你不知道的 super 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我 ...
- Gradle入门与使用
注:此篇博客主要是看官网的学习笔记:https://docs.gradle.org/current/userguide/installation.html 一.安装: 1.Gradle有内置的groo ...
- (77)Wangdao.com第十五天_JavaScript 用于数据交换的文本格式 JSON 对象
JSON 对象 JSON (JavaScript Object Notation 的缩写) 也是一种数据,是 JavaScript 的原生对象,用来处理 JSON 格式数据.它有两个静态方法:JSON ...
- JS的javascript:void(0)用法
javascript:void(0)用法如下: <a href="javascript:void(0)"></a> // 执行js函数,0表示不执行函数. ...
- javaweb 与jsp页面的交互流程 (初次接触时写)
javaweb 与jsp页面的交互流程 javaweb项目目录 1. javaweb项目的一般目录: 2. jsp 页面一般情况下放在 top(前台页面) back(后台页面) 3. 后台代码 放在s ...
- 全排列筛选(java)
蓝桥杯-全排列筛选(java) 蓝桥杯每年必考全排列筛选,一般为填空题: 可以使用for循环暴力破解,但是代码相对较长,也比较乱,不建议使用: 这里使用递归来解决,代码量相对较少,也很好理解: 如下为 ...
- MYSQL 导入导出数据库文件
一.从数据库导出数据库或表文件: mysqldump -u用戶名 -p密码 -d 数据库名 表名 > 脚本名; 导出整个数据库结构和数据mysqldump -h localhost -uroot ...