Windows Developer Days – WA-021 ライブコーディングのシナリオメモ


Windows Phone アプリの Metro スタイル アプリへの移植

https://channel9.msdn.com/Events/Windows-Developer-Days/Windows-Developer-Days-2012/WA-021

でお見せしたライブコーディングのデモシナリオのメモを、その当時のまま、公開します。
※ Windows 8 Consumer PreviewとVisual Studio 11 Beta用なので、ご注意ください。 

ライブコーディングで見る Windows Phone から Windows 8への移植

・Windows Phone SDK 7.1.1 で TweetTileアプリケーションを作成
  @oniak3 用にデザイン、ビルドして実行

・VS 11 Beta、Windows Metro Style 新しいアプリケーション作成

・Windows Phone側のプロジェクトから、Assetsフォルダをコピー

・BlankPageに対して、Windows Phone側のMainPage.xamlから XAMLをコピー
  <DataTemplate>を <Page.Resources>へ追加

 <Grid Background="{ .. }"> の中に次を追加

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel は、アプリケーション名とページ タイトルを格納します-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="WDDデモ中" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="@oniak3" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="64" />
        </StackPanel>

        <!--ContentPanel - 追加コンテンツをここに入力します-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Image Source="Images/CG019.jpg" Stretch="UniformToFill" Opacity="0.1"/>
            <ListBox ItemTemplate="{StaticResource SyndicationItemTemplate}" ItemsSource="{Binding Items}" Name="listResult" DoubleTapped="listResult_DoubleTapped_1"/>
        </Grid>

・ビルドし、エラーを確認
 DoubleTap イベントは DoubleTapped へ変更して新たに作る

・Windows Phone SDKからリソースファイルとして、
C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Design
にある、ThemeResources.xamlをVS11側へコピーする

・Windows Phone側のMainPage.xaml.csからコードをコピー

 ダブルタップやShareStatusなどのコードはコメントアウト

・GetTweets/GetUserTimelineをリファクタリングし、データ読み込み部分をGetFeedメソッド化する

 SyndicationFeed feed;
 private async void GetFeed(Uri u)
 {
  SyndicationClient cli = new SyndicationClient();
  cli.BypassCacheOnRetrieve = true;
  feed = await cli.RetrieveFeedAsync(u);
  this.DataContext = feed;
 }

・ビルドして実行
 画像や投稿者が表示されない
 デバッガーで止めてみる、いつもと異なるエラーが見られるので、ここは純粋にモデルを作る

・FeedItem.csの追加
 フィードを格納するクラスを用意する

    public class FeedData
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public DateTime PubDate { get; set; }

        private List<FeedItem> _Items = new List<FeedItem>();
        public List<FeedItem> Items
        {
            get
            {
                return this._Items;
            }
        }
    }

    // FeedItem
    // Holds info for a single blog post
    public class FeedItem
    {
        public string Title { get; set; }
        public string Author { get; set; }
        public string Content { get; set; }
        public DateTime PubDate { get; set; }
        public Uri Link { get; set; }
        public string IconUri { get; set; }
    }

・GetFeedの修正
        private async void GetFeed(Uri u)
        {
            SyndicationClient cli = new SyndicationClient();
            cli.BypassCacheOnRetrieve = true;
            SyndicationFeed feed = await cli.RetrieveFeedAsync(u);
            FeedData feedData = new FeedData();
            feedData.Title = feed.Title.Text;

            foreach (SyndicationItem item in feed.Items)
            {
                FeedItem feedItem = new FeedItem();
                feedItem.Title = item.Title.Text;
                feedItem.PubDate = item.PublishedDate.DateTime;
                feedItem.Author = item.Authors[0].Name.ToString();
                feedItem.IconUri = item.Links[1].Uri.AbsoluteUri;
                feedItem.Link = item.Links[0].Uri;
                if (feed.SourceFormat == SyndicationFormat.Atom10)
                {
                    feedItem.Content = item.Content.Text;
                }
                else if (feed.SourceFormat == SyndicationFormat.Rss20)
                {
                    feedItem.Content = item.Summary.Text;
                }
                feedData.Items.Add(feedItem);
            }
            this.DataContext = feedData;

        }

・XAMLのDataTemplateの修正
        <DataTemplate x:Key="SyndicationItemTemplate">
            <StackPanel Orientation="Horizontal" Width="460">
                <Image Height="91" Width="91" Source="{Binding IconUri}" Margin="4"/>
                <StackPanel Orientation="Vertical" Width="350">
                    <TextBlock Text="{Binding Author}" FontWeight="Bold" >
                    <TextBlock.Foreground>
                        <SolidColorBrush Color="{StaticResource PhoneAccentColor}"/>
                    </TextBlock.Foreground>

                    </TextBlock>
                    <TextBlock TextWrapping="Wrap" Text="{Binding Title}"  />
                </StackPanel>
            </StackPanel>
        </DataTemplate>

・ビルドして実行、画像などが表示されたことを確認する

・XAMLのListBoxをListView/GridViewに変更する
 それっぽくなる

・AppBarの実装、BlankPage.xaml側
 Windows PhoneのApplicationBarのメニューから持ってきて修正して見せる
 Clickイベントハンドラは作り直す

    <Page.BottomAppBar>
        <AppBar>
            <StackPanel Orientation="Horizontal">
            <Button x:Name="menuSearch" Content="皆さんのメッセージを表示" Click="menuSearch_Click_1"/>
            <Button x:Name="menuUserTimeline" Content="私のツィートを表示" Click="menuUserTimeline_Click_1"/>
            <Button x:Name="menuShareStatus" Content="メッセージの投稿" Click="menuShareStatus_Click_1"/>
            </StackPanel>
        </AppBar>
    </Page.BottomAppBar>

・BlankPage.xaml.cs側
 GetUserTimeline()やGetTweets()を正しくマップする

        private void menuSearch_Click_1(object sender, RoutedEventArgs e)
        {
            GetTweets(TwitterId);
        }

        private void menuUserTimeline_Click_1(object sender, RoutedEventArgs e)
        {
            GetUserTimeline(TwitterId);
        }

・ビルドして実行、画面右下にマウスを移動させ、右クリックでメニューを表示させる
 タイムラインやメンションに切り替わるのを確認
 ただし、APIの呼び出し制限でうまくできないことも踏まえておこう

・リストのダブルタップによるブラウザー実行
 WebBrowserTaskではなく、Launcher.LaunchUriAsyncメソッド

            FeedItem i = listResult.SelectedItem as FeedItem;
            Windows.System.Launcher.LaunchUriAsync(i.Link);

 Metro スタイルのIE 10が実行されることを確認

・共有コントラクトの設定
 ShareStatusTaskはないが、もっとリッチな共有コントラクトを利用できる

        public BlankPage()
        {
            this.InitializeComponent();
            SetShareContract();
            GetTweets(TwitterId);

        }

        public string dataPackageTitle { get; set; }
        public string dataPackageDescription { get; set; }
        public string dataPackageText { get; set; }

        private void SetShareContract()
        {
            // チャームを表示された場合の対策
            dataPackageTitle = "メッセージ送信";
            dataPackageDescription = "共有コントラクトで送ろう";
            dataPackageText = "@" + TwitterId + "、がんばって!";
            DataTransferManager dtm = DataTransferManager.GetForCurrentView();
            dtm.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.dtm_DataRequested);

        }
        void dtm_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
        {
            args.Request.Data.Properties.Title = this.dataPackageTitle;
            args.Request.Data.Properties.Description = this.dataPackageDescription;
            args.Request.Data.SetText(this.dataPackageText);
        }

        private void menuShareStatus_Click_1(object sender, RoutedEventArgs e)
        {
            dataPackageTitle = "メッセージ送信";
            dataPackageDescription = "共有コントラクトで送ろう";
            dataPackageText = "@" + TwitterId + "、がんばって!";
            DataTransferManager.ShowShareUI();
        }

・以上、どうでしょう?
 画面の最適化は別の課題として考え、機能が同じレベルに移植するまでのプロセスをデモでご紹介しました。

Skip to main content