Xamarin.Forms:获取列表视图的所有单元格/项目
Posted
技术标签:
【中文标题】Xamarin.Forms:获取列表视图的所有单元格/项目【英文标题】:Xamarin.Forms: Get all cells/items of a listview 【发布时间】:2016-06-21 07:47:42 【问题描述】:我想对ListView 中显示的所有单元格进行一些更改。因此,我想获取所有单元格或项目。例如
this.listView.ItemSource.Items
上述代码中的 Items 不存在。此外,我在ListView
或ItemSource
上没有找到任何可以做到这一点的选项。是否可以获得所有单元格/项目?如果不是,我还必须在加载单元格后更改哪些其他选项?例如。用于更改文本或布局。
【问题讨论】:
【参考方案1】:我可能迟到了,但这里有另一种使用 System.Reflection 的方法。无论如何,我建议仅在无法进行数据绑定的情况下使用它,并将其作为最后的选择。
对于给定的 ListView
<ListView x:Name="connectionsListView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemSelected="OnConnectionSelect">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="40">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<customs:MyViewClass Grid.Column="0"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<ContentView />
</ListView.Footer>
</ListView>
您可以通过抓取“TemplatedItems”属性来爬取 ListView,
将其投射到ITemplatedItemsList<Cell>
并遍历您的(视图)单元格。
IEnumerable<PropertyInfo> pInfos = (connectionsListView as ItemsView<Cell>).GetType().GetRuntimeProperties();
var templatedItems = pInfos.FirstOrDefault(info => info.Name == "TemplatedItems");
if (templatedItems != null)
var cells = templatedItems.GetValue(connectionsListView);
foreach (ViewCell cell in cells as Xamarin.Forms.ITemplatedItemsList<Xamarin.Forms.Cell>)
if (cell.BindingContext != null && cell.BindingContext is MyModelClass)
MyViewClass target = (cell.View as Grid).Children.OfType<MyViewClass>().FirstOrDefault();
if (target != null)
//do whatever you want to do with your item...
更新: 既然被问到, if (cell.BindingContext != null && cell.BindingContext is MyModelClass) 基本上是防止访问不存在的视图的保护措施,例如,如果尚未填充 ListView。
如果不需要检查 BindingContext 是否为特定模型类,则将行减少到
if (cell.BindingContext != null)
【讨论】:
抱歉这个愚蠢的问题,MyViewClass 到底指的是什么? 如果我没猜错的话,比如标签/开关/按钮。 是的,MyViewClass 是您添加到列表中并现在要查找的任何类的占位符。 我喜欢这种方法,到目前为止我遇到的唯一问题是使用分组列表视图时。 “单元格”将仅包含组标题。还是很整洁 @MarkusMichel,是否有可能拥有 ViewCell 的高度?似乎总是-1【参考方案2】:通常,您不会直接触摸您的细胞。相反,如果可能,您会尝试通过数据绑定来完成所有事情。
让我们使用 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="App6.Page1">
<ListView x:Name="myList"
BackgroundColor="Gray"
ItemsSource="Binding MyItems"
HasUnevenRows="true"
RowHeight="-1">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="StartAndExpand"
Padding="15, 10, 10, 10"
BackgroundColor="White">
<Label Text="Binding Title"
FontSize="18"
TextColor="Black"
VerticalOptions="StartAndExpand"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
在您的 Page 中,您将 ViewModel 设置为 BindingContext。
public partial class Page1 : ContentPage
public Page1()
InitializeComponent();
BindingContext = new Page1ViewModel();
并且您的 ViewModel 在 ObservableCollection 中包含您的 Items MyItems
,这意味着如果您添加或删除 Items,您的视图会更新。此属性绑定为您 List 的 ItemsSource(请参阅 XAML:ItemsSource="Binding MyItems"
)。
class Page1ViewModel : INotifyPropertyChanged
private ObservableCollection<MyItem> _myItems = new ObservableCollection<MyItem>();
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<MyItem> MyItems
get return _myItems;
set
_myItems = value;
OnPropertyChanged();
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public Page1ViewModel()
MyItems.Add(new MyItem Title = "Test" );
MyItems.Add(new MyItem Title = "Test2" );
MyItems.Add(new MyItem Title = "Test3" );
MyItems.Add(new MyItem Title = "Test4" );
MyItems.Add(new MyItem Title = "Test5" );
public void ChangeItem()
MyItems[1].Title = "Hello World";
对于每个项目,您都有一个代表一个单元格数据的对象。此项的类型实现INotifyPropertyChanged
。这意味着,它会通知已更改的属性。数据绑定机制注册到此事件,并在引发时更新视图。
public class MyItem : INotifyPropertyChanged
private string _title;
public string Title
get return _title;
set
_title = value;
OnPropertyChanged(); // Notify, that Title has been changed
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
如果您现在更改其中一项,例如致电ChangeItem()
。然后第二个单元格的标签将更新为"Hello World"
,因为它绑定到标题(请参阅 XAML Text="Binding Title"
)。
这一切背后的一般思想称为 MvvM 模式,您希望将视图与视图逻辑和模型(数据/服务,...)分开。
【讨论】:
我想这个答案对提出问题的人有所帮助,但在我的情况下,单元格的内容已经改变,这会影响它的高度。在 ios 中,高度似乎不会自动增长,因此单元格中的新单词会与下一个单元格中的单词重叠。我想在刚刚更改的单元格上使用 Cell.ForceUpdateSize,但在我看来,我需要获取实际的单元格对象才能做到这一点。以上是关于Xamarin.Forms:获取列表视图的所有单元格/项目的主要内容,如果未能解决你的问题,请参考以下文章