2016-03-07 96 views
2

我想对ListView中显示的所有单元格进行一些更改。因此我想获取所有单元格或项目。例如。Xamarin.Forms:获取列表视图的所有单元格/项目

this.listView.ItemSource.Items 

物品在上面的代码中不存在。此外,我没有在ListViewItemSource上找到任何选项,可以做到这一点。是否有可能获得所有细胞/物品?如果没有其他选择,我必须在装载后改变单元格的外观?例如。用于更改文本或布局。

回答

5

通常情况下,您不直接触摸您的细胞。相反,如果可能的话,您尝试通过数据绑定来做所有事情。

让我们使用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> 

在你的页面,您可以设置您的视图模型为BindingContext中。

public partial class Page1 : ContentPage 
{ 
    public Page1() 
    { 
     InitializeComponent(); 
     BindingContext = new Page1ViewModel(); 
    } 
} 

而且你的视图模型包含的项目MyItems在一个ObservableCollection,这意味着你的视图更新,如果您添加或删除项目。此属性绑定为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模式,您希望将视图从视图逻辑和模型(数据/服务......)中分离出来。

2

我可能迟到了派对,但这里有另一种使用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”属性, 它铸造ITemplatedItemsList<Cell>并通过您(查看)细胞遍历ListView的抓取。

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... 
      } 
     } 
    } 
}