如何将现有RadListView定义为资源以在多页面复用并绑定不同数据源?
复用RadListView作为可复用资源的最优方案
要实现你这个RadListView的复用(包括它的ItemTemplate和基础配置),最干净高效的方式是把它封装成自定义控件,这样其他页面直接引用就能用,不用重复写一大段模板代码。下面给你两种可行方案,你可以根据自己的需求选择:
方案一:封装成自定义RadListView控件(推荐)
这种方案把整个ListView的布局、模板和预设属性都封装起来,只对外暴露需要动态绑定的属性(比如ItemsSource、SelectedItem、HeightRequest),完美适配你的需求——复用整个ListView,只换数据源。
第一步:创建自定义控件的XAML文件
新建一个名为ReusableStudyListView.xaml的文件,把你的ListView模板和配置放进去:
<?xml version="1.0" encoding="UTF-8"?> <dataControls:RadListView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:dataControls="clr-namespace:Telerik.XamarinForms.DataControls;assembly=Telerik.XamarinForms.DataControls" xmlns:listView="clr-namespace:Telerik.XamarinForms.DataControls.ListView;assembly=Telerik.XamarinForms.DataControls" xmlns:maxline="clr-namespace:YourAppNamespace" <!-- 替换成XfMaxLinesLabel所在的命名空间 --> x:Class="YourAppNamespace.ReusableStudyListView" MinimumHeightRequest="70" x:Name="InternalListView"> <dataControls:RadListView.ItemTemplate> <DataTemplate> <listView:ListViewTemplateCell> <listView:ListViewTemplateCell.View> <Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand"> <StackLayout Padding="5,1,1,5" Grid.Column="0"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/> </Grid> <StackLayout Padding="0,0,0,0" HorizontalOptions="Fill"> <BoxView Margin="0" BackgroundColor="Gray" HeightRequest=".25" /> <Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/> <BoxView Margin="0" BackgroundColor="Gray" HeightRequest=".25" /> </StackLayout> </StackLayout> </Grid> </listView:ListViewTemplateCell.View> </listView:ListViewTemplateCell> </DataTemplate> </dataControls:RadListView.ItemTemplate> </dataControls:RadListView>
第二步:编写自定义控件的后台代码
新建对应的后台文件ReusableStudyListView.xaml.cs,把需要外部绑定的属性暴露出来,和内部的ListView关联:
using Xamarin.Forms; using Telerik.XamarinForms.DataControls; namespace YourAppNamespace { public partial class ReusableStudyListView : RadListView { // 定义可绑定的ItemsSource属性 public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(object), typeof(ReusableStudyListView), null, propertyChanged: (bindable, oldValue, newValue) => { var control = (ReusableStudyListView)bindable; control.InternalListView.ItemsSource = newValue; }); // 定义可绑定的SelectedItem属性(双向绑定) public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(ReusableStudyListView), null, BindingMode.TwoWay, propertyChanged: (bindable, oldValue, newValue) => { var control = (ReusableStudyListView)bindable; control.InternalListView.SelectedItem = newValue; }); // 定义可绑定的HeightRequest属性 public static readonly BindableProperty HeightRequestProperty = BindableProperty.Create(nameof(HeightRequest), typeof(double), typeof(ReusableStudyListView), 0.0, propertyChanged: (bindable, oldValue, newValue) => { var control = (ReusableStudyListView)bindable; control.InternalListView.HeightRequest = (double)newValue; }); // 属性的get/set方法 public object ItemsSource { get => GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value); } public object SelectedItem { get => GetValue(SelectedItemProperty); set => SetValue(SelectedItemProperty, value); } public new double HeightRequest { get => (double)GetValue(HeightRequestProperty); set => SetValue(HeightRequestProperty, value); } public ReusableStudyListView() { InitializeComponent(); // 同步内部ListView的选中变化到外部属性 InternalListView.SelectedItemChanged += (s, e) => SelectedItem = InternalListView.SelectedItem; } } }
第三步:在其他页面复用这个自定义控件
现在你可以在任何页面里直接用这个控件,只需要绑定对应的数据源和属性就行:
<?xml version="1.0" encoding="utf-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:controls="clr-namespace:YourAppNamespace" <!-- 替换成自定义控件所在的命名空间 --> x:Class="YourAppNamespace.YourTargetPage"> <StackLayout> <!-- 直接引用自定义控件,绑定需要的属性 --> <controls:ReusableStudyListView ItemsSource="{Binding YourOtherStudyResults}" SelectedItem="{Binding YourSelectedItem, Mode=TwoWay}" HeightRequest="{Binding YourListHeight}"/> </StackLayout> </ContentPage>
方案二:将ItemTemplate作为全局资源(灵活复用模板)
如果你只是想复用ItemTemplate,而ListView的其他属性(比如HeightRequest)在不同页面需要调整,可以把模板放到全局资源字典里:
第一步:在App.xaml中添加全局模板
<Application.Resources> <ResourceDictionary> <!-- 你的其他静态资源(比如ListViewLabelStyle) --> <DataTemplate x:Key="StudyItemTemplate"> <listView:ListViewTemplateCell> <listView:ListViewTemplateCell.View> <Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand"> <StackLayout Padding="5,1,1,5" Grid.Column="0"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/> </Grid> <StackLayout Padding="0,0,0,0" HorizontalOptions="Fill"> <BoxView Margin="0" BackgroundColor="Gray" HeightRequest=".25" /> <Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/> <BoxView Margin="0" BackgroundColor="Gray" HeightRequest=".25" /> </StackLayout> </StackLayout> </Grid> </listView:ListViewTemplateCell.View> </listView:ListViewTemplateCell> </DataTemplate> </ResourceDictionary> </Application.Resources>
第二步:在页面中使用这个模板
<dataControls:RadListView x:Name="ItemsListView" ItemsSource="{Binding YourStudyResults, Mode=TwoWay}" MinimumHeightRequest="70" HeightRequest="{Binding YourHeight}" SelectedItem="{Binding YourSelectedItem, Mode=TwoWay}" ItemTemplate="{StaticResource StudyItemTemplate}"/>
方案对比
- 自定义控件方案:封装最彻底,完全复用整个ListView的配置,页面代码最简洁,还能保证所有使用该控件的页面UI一致,强烈推荐。
- 全局模板方案:更灵活,适合需要在不同页面调整ListView其他属性的场景,但页面中还是要写ListView的基础配置代码。
内容的提问来源于stack exchange,提问作者ajit
相关产品推荐
相关产品推荐

