しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Xamarin.Forms で RSS フィードを ListView に表示したい

前回 は Xamarin.Forms で TechCrunch の RSS フィードを取得したので、今度は ListView に表示してみたいと思います

まずはおなじみ UnityContainer と Prism を NuGet でパッケージインストール

インストールしたら App クラスを修正


/// <summary>
/// Application class
/// </summary>
public class App : Application
{
    /// <summary>
    /// Dependency injection container
    /// </summary>
    public IUnityContainer Container = new UnityContainer();

    /// <summary>
    /// Costructor
    /// </summary>
    public App()
    {
        this.Container.RegisterType<INewsFeedService, NewsFeedService>(new ContainerControlledLifetimeManager());

        this.MainPage = new TopPage();
    }

    /// <summary>
    /// Application start event handler
    /// </summary>
    protected override void OnStart()
    {
    }

    /// <summary>
    /// Application suspend event handler
    /// </summary>
    protected override void OnSleep()
    {
    }

    /// <summary>
    /// Application resume event handler
    /// </summary>
    protected override void OnResume()
    {
    }
}

前回作った NewsFeedService は INewsFeedService のインタフェースつきに変更して UnityContainer 経由でアクセスするようにしました

次に TopPage のコードビハインド

/// <summary>
/// Top page
/// </summary>
public partial class TopPage : ContentPage
{
    /// <summary>
    /// Remove html tag regex
    /// </summary>
    private static readonly Regex HtmlTagRegex = new Regex(@"<.*?>", RegexOptions.Singleline);

    /// <summary>
    /// News feed retrieve service
    /// </summary>
    private INewsFeedService newsFeed = null;

    /// <summary>
    /// ViewModel
    /// </summary>
    public TopPageViewModel ViewModel { get; private set; }

    /// <summary>
    /// Constructir
    /// </summary>
    public TopPage()
    {
        this.ViewModel = new TopPageViewModel();
        this.newsFeed = ((App)App.Current).Container.Resolve<INewsFeedService>();

        InitializeComponent();
    }

    /// <summary>
    /// Appearing event handler
    /// </summary>
    protected override async void OnAppearing()
    {
        base.OnAppearing();

        await this.newsFeed.Update();

        // Add items on UI thread
        foreach (var item in this.newsFeed.Feed.Channel.Items)
        {
            this.ViewModel.Items.Add(new NewsItemViewModel
            {
                UniqueId = item.Guid,
                Categories = new ObservableCollection<string>(item.Categories),
                Title = item.Title,
                Link = item.Link,
                LastUpdated = item.PubDate,
                Description = WebUtility.HtmlDecode(HtmlTagRegex.Replace(item.Description, string.Empty)),
            });
        }
    }
}

Windows 10 のストアアプリの書き方にのってコードビハインドに ViewModel のプロパティを生やしました

画面表示のとき(OnAppearing)に、UnityContainer から NewsFeedService をとってきて TechCrunch のフィードを取得します

取得したフィードは ViewModel にデータを移し替えてます・・・Description の中身は HTML なので、タグを正規表現で削除したり、&nbsp; などを WebUtility で変換したりしてます

TopPageViewModel は Prism の BindableBase を継承したただの ViewModel なので省略します!

さて 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="XamarinReader.Views.TopPage"
             x:Name="root"
             BindingContext="{Binding Path=ViewModel, Source={x:Reference Name=root}}">
    <ListView ItemsSource="{Binding Items}"
              HasUnevenRows="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Vertical"
                                 Padding="15,10"
                                 Spacing="10">
                        <Label Text="{Binding Title}"
                               TextColor="Accent"
                               FontSize="Medium"/>
                        <Label Text="{Binding Description}"
                               TextColor="Default"
                               FontSize="Small"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

ListView で Title と Description を縦に並べて表示するレイアウト

BindingContext は コードビハインドの ViewModel プロパティにバインドするようにこんな感じで記述します

あと忘れちゃいけない ListView.HasUnevenRows="True"

これが指定されていないとリストの高さが固定されちゃうので注意

さくっと書いたら試してみました

f:id:matatabi_ux:20150814221302g:plain

ちゃんとリストごとにテキストの長さに合わせた高さになってますね