Posted at

ListViewの内容を動的に更新したい場合はObservableCollectionを利用する

More than 3 years have passed since last update.

例えばこんなView(ChatPage.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="MessageApp.Views.ChatPage">
<ContentPage.Content>
<StackLayout>
<ListView x:Name="messagesView" VerticalOptions="FillAndExpand"></ListView>
<StackLayout Orientation="Vertical" VerticalOptions="End">
<Entry x:Name="message" Placeholder="Write something here..." Keyboard="Chat" />
<Button Text="Send" WidthRequest="80" Clicked="OnSendTapped" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

こんな動作を期待しているときに、

iPhone_6s_-_iPhone_6s___iOS_9_3__13E230_.png

こんな風なView(ChatPage.xaml.cs)を書いても期待した動作にはならない。

using System;

using System.Collections.Generic;
using Xamarin.Forms;

namespace MessageApp.Views
{
public partial class ChatPage : ContentPage
{
private List<string> messages = new List<string>();

public ChatPage()
{
InitializeComponent();
Title = "Message";
messagesView.ItemsSource = messages;
}

void OnSendTapped(object sender, EventArgs args)
{
messages.Add(message.Text);
message.Text = "";
}
}
}

ListのオブジェクトをItemSourceとして指定しても、ListView側が変更を検知できないので、変更を検知させたい場合はObservableCollectionを利用する必要がある。修正後のコードがこちら。

using System;

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.Forms;

namespace MessageApp.Views
{
public partial class ChatPage : ContentPage
{
private ObservableCollection<string> messages = new ObservableCollection<string>();

public ChatPage()
{
InitializeComponent();
Title = "Message";
messagesView.ItemsSource = messages;
}

void OnSendTapped(object sender, EventArgs args)
{
messages.Add(message.Text);
message.Text = "";
}
}
}

参考:ListView Data Sources: Data Binding