Xamarin.Android中FindViewById无法识别Xamarin.Forms.ListView问题
问题分析与解决方案
你遇到的核心问题是混淆了Xamarin.Android原生控件和Xamarin.Forms控件的使用场景——Xamarin.Android的原生Activity页面里,根本无法直接使用Xamarin.Forms的ListView控件,这就是FindViewById找不到它的原因。下面分两种方案帮你解决:
方案一:继续使用Xamarin.Android原生实现(推荐当前场景)
既然你是在Xamarin.Android的Activity里开发,就应该用Android原生的Android.Widget.ListView,通过自定义Adapter来绑定你的自定义类集合。
步骤1:修改布局XML
把布局里的Xamarin.Forms.ListView替换成原生Android的ListView:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:minWidth="25dp" android:minHeight="25dp"> <!-- 改为原生ListView --> <ListView android:layout_width="match_parent" android:layout_height="200dp" android:id="@+id/mainlistview"/> <TextView android:text="Layout1Activity" android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/textView1" /> <Button android:text="BACK" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/button1" android:onClick="GoBack"/> </LinearLayout>
步骤2:自定义Adapter绑定数据
因为你要绑定自定义的VehicleReg类,需要写一个继承自BaseAdapter的自定义适配器:
using Android.App; using Android.Content; using Android.Views; using Android.Widget; using System.Collections.Generic; namespace Landfill_App { public class VehicleRegAdapter : BaseAdapter<VehicleReg> { private readonly List<VehicleReg> _data; private readonly Context _context; public VehicleRegAdapter(Context context, List<VehicleReg> data) { _context = context; _data = data; } public override VehicleReg this[int position] => _data[position]; public override int Count => _data.Count; public override long GetItemId(int position) => position; public override View GetView(int position, View convertView, ViewGroup parent) { // 复用视图提升性能 View view = convertView ?? LayoutInflater.From(_context).Inflate(Android.Resource.Layout.SimpleListItem2, parent, false); // 获取当前数据项 var item = _data[position]; // 绑定数据到原生布局的两个TextView view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = item.Reg; view.FindViewById<TextView>(Android.Resource.Id.Text2).Text = item.Weight.ToString("F2"); return view; } } }
步骤3:修改Activity代码
把原来的Xamarin.Forms.ListView替换成原生的,并设置自定义Adapter:
using System.Collections.Generic; using Android.App; using Android.Content; using Android.OS; using Android.Widget; namespace Landfill_App { [Activity(Label = "Vehicle Reg")] public class Activity1 : Activity { // 使用原生Android的ListView private Android.Widget.ListView _mainList; private List<VehicleReg> _regs = new List<VehicleReg>(); protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.layout1); _mainList = FindViewById<Android.Widget.ListView>(Resource.Id.mainlistview); // 添加测试数据 _regs.Add(new VehicleReg() { Reg = "GHJ6786", Weight = 250.56M }); _regs.Add(new VehicleReg() { Reg = "ABC1234", Weight = 300.78M }); // 设置适配器绑定数据 _mainList.Adapter = new VehicleRegAdapter(this, _regs); } // 返回按钮的点击事件 public void GoBack(View v) { Finish(); } } // 你的自定义VehicleReg类(补充完整) public class VehicleReg { public string Reg { get; set; } public decimal Weight { get; set; } } }
方案二:切换到Xamarin.Forms实现(适合跨平台需求)
如果你想使用ItemsSource这种更简洁的绑定方式,那应该切换到Xamarin.Forms项目结构,因为Xamarin.Forms.ListView是跨平台框架的控件,只能在Xamarin.Forms的ContentPage中使用。
示例代码(Xamarin.Forms页面)
XAML页面:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Landfill_App.VehicleRegPage" Title="Vehicle Reg"> <StackLayout Padding="10"> <ListView ItemsSource="{Binding Regs}" HeightRequest="200"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal" Padding="5"> <Label Text="{Binding Reg}" FontSize="Medium" FontAttributes="Bold"/> <Label Text="{Binding Weight, StringFormat='Weight: {0:F2}kg'}" Margin="10,0,0,0"/> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> <Label Text="Layout1Activity" Margin="0,10,0,0"/> <Button Text="BACK" Clicked="GoBack_Clicked" Margin="0,10,0,0"/> </StackLayout> </ContentPage>
后台代码与ViewModel:
using System.Collections.ObjectModel; using Xamarin.Forms; namespace Landfill_App { public partial class VehicleRegPage : ContentPage { public VehicleRegPage() { InitializeComponent(); BindingContext = new VehicleRegViewModel(); } private void GoBack_Clicked(object sender, EventArgs e) { Navigation.PopAsync(); } } public class VehicleRegViewModel { public ObservableCollection<VehicleReg> Regs { get; set; } public VehicleRegViewModel() { Regs = new ObservableCollection<VehicleReg>(); Regs.Add(new VehicleReg() { Reg = "GHJ6786", Weight = 250.56M }); } } public class VehicleReg { public string Reg { get; set; } public decimal Weight { get; set; } } }
内容的提问来源于stack exchange,提问作者Ross Crooks
相关产品推荐
相关产品推荐

