Xamarin中如何将View绑定到ListView的ViewCell并正确渲染内容
问题原因
你遇到的问题本质是ListView的ItemsSource属性绑定的是数据源集合,而非直接的视图控件集合,当你把ViewCell类型对象作为数据项绑定时,ListView没有对应的渲染模板,就会默认调用ToString()方法展示类型名,而且这种在ViewModel中定义视图控件的写法也不符合MVVM的分层原则。
方案1:遵循MVVM规范的标准实现(推荐)
1. 定义数据模型
新建用于标识列表项内容的模型类:
public class ListItemModel { // 用来区分项的类型:测量/图案/其他 public string ItemType { get; set; } // 存储展示文本 public string ContentText { get; set; } // 其他你需要的业务属性都可以加在这里 }
2. 调整ViewModel代码
把集合类型替换为数据模型集合,新增逻辑改为添加数据对象:
// 把原来的ViewCell集合改为数据模型集合 public ObservableCollection<ListItemModel> DataTemplate { get; set; } = new(); private void NewOther(object obj) { IsBusy = true; try { DataTemplate.Add(new ListItemModel { ItemType = "Other", ContentText = "I m New" }); } catch (Exception ex) { Debug.WriteLine(ex); } finally { IsBusy = false; } }
3. 修改XAML添加项模板
给ListView添加ItemTemplate指定渲染规则,如果不同类型的项布局不同,可以搭配DataTemplateSelector实现动态布局:
<RefreshView Padding="5" Command="{Binding LoadCheckListsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}"> <ListView ItemsSource="{Binding DataTemplate}"> <!-- 新增ItemTemplate定义每一项的渲染方式 --> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Label Text="{Binding ContentText}"/> <!-- 这里可以根据ItemType绑定不同的控件、样式 --> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> <ListView.Header> <Grid ColumnDefinitions="*,*,*"> <Button Text="Add Measurment" Grid.Column="0" Command="{Binding AddMeasurment}"/> <Button Text="Add Pattern" Grid.Column="1" Command="{Binding AddPattern}"/> <Button Text="Add Other" Grid.Column="2" Command="{Binding AddOther}"/> </Grid> </ListView.Header> <ListView.Footer> <StackLayout Orientation="Horizontal" Margin="0,10,0,0"> <Button Text="Cancel" Command="{Binding CancelCommand}" HorizontalOptions="FillAndExpand"></Button> <Button Text="Save" Command="{Binding SaveCommand}" HorizontalOptions="FillAndExpand"></Button> </StackLayout> </ListView.Footer> </ListView> </RefreshView>
方案2:兼容现有代码的快速实现(不推荐,违反MVVM原则)
如果你暂时不想调整现有逻辑,只需要在XAML的ListView中显式指定ItemTemplate,直接绑定ViewCell的View属性即可:
<ListView ItemsSource="{Binding dataTemplate}"> <ListView.ItemTemplate> <DataTemplate> <!-- 直接把绑定的ViewCell对象的View属性赋值给当前ViewCell --> <ViewCell View="{Binding View}"/> </DataTemplate> </ListView.ItemTemplate> <!-- 其余原有代码不变 --> </ListView>
这种写法相当于你自己构造了完整的ViewCell,ListView只需要取你构造好的View属性渲染即可,不需要再自己生成视图。
内容的提问来源于stack exchange,提问作者Denis Brazhnichenko
相关产品推荐
相关产品推荐

