第十九章:集合視圖(六)

ObservableCollection的區別
ListView的ItemsSource屬性的類型爲IEnumerable。 數組實現IEnumerable接口,List和List 類也是如此。 List和List 集合特別適合ListView,因爲這些類可以動態地重新分配內存以容納幾乎任何大小的集合。
您已經看到,在將集合分配給ListView的ItemsSource屬性後,可以對其進行修改。 應該可以在ItemsSource引用的集合中添加項目或刪除項目,並使ListView更新自身以反映這些更改。
我們來試試吧。 此ListViewLogger程序在其XAML文件中實例化ListView:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ListViewLogger.ListViewLoggerPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="10, 20, 10, 0"
                    Android="10, 0"
                    WinPhone="10, 0" />
    </ContentPage.Padding>
 <ListView x:Name="listView" />
</ContentPage>

代碼隱藏文件將ListView的ItemsSource屬性設置爲List 對象,並每秒向此集合添加一個DateTime值:

public partial class ListViewLoggerPage : ContentPage
{
    public ListViewLoggerPage()
    {
        InitializeComponent();
        List<DateTime> list = new List<DateTime>();
        listView.ItemsSource = list;
        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
        {
            list.Add(DateTime.Now);
            return true;
        });
    }
}

當你第一次運行這個程序時,似乎什麼也沒發生。但是,如果您將手機或模擬器側向轉動,則會顯示自程序啓動以來已添加到集合中的所有項目。但是在你再次轉動手機的方向之前,你將不再看到它。
發生了什麼?當ListView需要重繪時 - 更改手機或模擬器的方向時會出現這種情況 - 它將使用當前的IEnumerable集合。 (這是ListViewArray程序顯示排序數組的方式。數組在ListView第一次顯示之前已經排序。)
但是,如果ListView不需要重繪自身,則ListView無法知道何時將項添加到集合中或從集合中刪除。這不是ListView的錯。這真的是List類的錯誤。 List和List 類不實現在集合發生更改時通知ListView的通知機制。
爲了說服ListView使用新添加的數據更新其顯示,我們需要一個非常類似於List 的類,但它包含一個通知機制。
我們需要一個與ObservableCollection完全相同的類。
ObservableCollection是一個.NET類。它在System.Collections.ObjectModel命名空間中定義,它實現了一個名爲INotifyCollectionChanged的接口,該接口在System.Collections.Specialized命名空間中定義。在實現此接口時,只要在集合中添加或刪除項目,或者替換或重新排序項目時,ObservableCollection就會觸發CollectionChanged事件。
ListView如何知道ObservableCollection對象被設置爲其ItemsSource屬性?設置ItemsSource屬性後,ListView將檢查設置爲該屬性的對象是否實現INotifyCollectionChanged。如果是這樣,ListView會將CollectionChanged處理程序附加到集合以通知更改。每當集合發生更改時,ListView都會自行更新。
ObservableLogger程序與ListViewLogger程序完全相同,只是它使用ObservableCollection 而不是List 來維護集合:

public partial class ObservableLoggerPage : ContentPage
{
    public ObservableLoggerPage()
    {
        InitializeComponent();
        ObservableCollection<DateTime> list = new ObservableCollection<DateTime>();
        listView.ItemsSource = list;
        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
        {
            list.Add(DateTime.Now);
            return true;
        });
    }
}

現在ListView每秒更新一次。
當然,並非每個應用程序都需要這種功能,ObservableCollection對於那些沒有這種功能的應用程序來說太過分了。 但它是多功能ListView使用的重要組成部分。
有時您將使用一組數據項,並且集合本身不會動態更改 - 換句話說,它始終包含相同的對象 - 但各個項的屬性會發生變化。 ListView可以響應那種變化嗎?
是的它可以,你將在本章後面看到一個例子。 啓用ListView以響應各個項中的屬性更改不需要ObservableCollection或INotifyCollectionChanged。 但是數據項必須實現INotifyPropertyChanged,並且ListView必須使用稱爲單元格的對象顯示項目。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章