SQLの窓

2013年05月10日


Win8 ストア : ストアブランク テンプレート

SkyDrive へ移動

ダウンロードしたテンプレートは、『C:\Users\ユーザー名\Documents\Visual Studio 2012\Templates\ProjectTemplates\Visual C#\Windows Store』に保存します。

Windows Store フォルダは最初は存在しないので作成します( 好きな名前のフォルダでも Visual Studio から利用できます )
ソースコード表示 仕様 ❶ Page.Resources で XAML 内で利用する文字列を定義 ❷ テキストエリアを設置( ファイルの処理を想定しているので Package.appxmanifest に設定済 ) ❸ AppBar を XAML で定義 (ボタンを左側2つ、右側2つ定義) ❹ それぞれのボタンにイベントを定義 ❺ 保存ボタンのイベントで、MessageDialog の利用サンプルを実装 ❻ MessageDialog のイベントを別のソースコードに定義( partial ) ❼ TextResource.cs に、StaticResource 用のクラスを定義 ❽ MessageDialog 処理用の MsgBox クラス プロジェクト用固定文字列の定義部分
<Page.Resources>
	<local:TextResource
		x:Key="GlobalText"
		PageTitle="ストアブランク テンプレート"
		AppName="lightbox サンプルアプリケーション" />
</Page.Resources>

プロジェクト用固定文字列の参照部分
<TextBlock
	DataContext="{StaticResource GlobalText}"
	HorizontalAlignment="Left"
	Height="61"
	Margin="76,60,0,0"
	TextWrapping="Wrap"
	Text="{Binding PageTitle}"
	VerticalAlignment="Top"
	Width="1090"
	FontSize="40"
	FontWeight="Bold"
	FontFamily="Meiryo"
	>
</TextBlock>

次のテンプレートでファイルアクセスをするので、テキストエリアを設置しています。
<TextBox
	x:Name="TextData" 
	HorizontalAlignment="Left" 
	Height="209"
	Margin="36,37,0,0"
	TextWrapping="Wrap" 
	VerticalAlignment="Top"
	Width="580" 
	AcceptsReturn="True"/>

テキストエリアは、実際には TextBox で、AcceptsReturn="True" にする事によって複数行の入力が可能になります

また、ファイルのアクセスを想定して、Package.appxmanifest に『機能』と『宣言』の設定をしています
( ページのロードでは、『text.txt』というファイルの存在チェックのみ行っています )





Page.Resources の参照

XAML 内での参照は、『AppBar テンプレート / Win8 ストアアプリ(C#)』 では、一括で定義して参照していましたが、実際には DataContext に設定して、Binding のみで参照します。DataContext も、自分自身のものである必要は無く、親要素でも構わないので効率的に良い方法を選びます。

ソースコードから参照するには、少しやっかいですがそのような処理は専用クラス内で行えば良いと思います。ここでは、MsgBox クラスで、タイトルに使用するのに参照しています。この参照方法は、Framework のバージョンによって違っており、4.5 から Where メソッドが使用できます
// Page.Resources から TextResource を取得
var NameSpace = pg.GetType().Namespace;
var trs = pg.Resources.Values.Where(Value => Value.ToString() == NameSpace + ".TextResource");
TextResource tr = (TextResource)trs.First();
var Title = tr.PageTitle;
var AppName = tr.AppName;
var messageDialog = new MessageDialog(message, Title + " (" + AppName + ")");

MsgBox クラス

MsgBox の処理は結構煩雑なので、応答用と確認用を固定で、static メソッドとして定義しています。

❶ public static async void ShowAsync(MainPage pg, string ok, string cancel, string message, UICommandInvokedHandler handler)

OK か Cancel のメッセージボックスを開いて、指定したメッセージを表示して、指定したイベントを応答に使用する。
仕様コード
MsgBox.ShowAsync(
	this,
	"OK",
	"Cancel",
	"データを保存しますか?",
	this.CommandInvokedHandler
);
❷ public static async void ShowAsync(MainPage pg, string ok, string message) イベントは使用せずにメッセージボックスのみが開く。 OnNavigatedTo で取得するパラメータ用構造体 ページを表示する時に、Frame クラスの Navigate(typeof(MainPage), 引き渡すオブジェクト) という形で呼び出します。この呼び出しは、MainPage のインスタンスが新しく作成される方法なので、最初以外は望ましくありませんが、他のページを呼び出したい時の引数として使ってコードがわかりやすくなるかもしれません。 その為のテンプレートとして、App.xaml.cs に定義して初回に使用して呼び出しています 受け取るのは、MainPage 側の OnNavigateTo イベント(Page の protected イベント)です
// *************************************************
// このページがフレームに表示されるときに呼び出されます。
// *************************************************
protected override void OnNavigatedTo(NavigationEventArgs e)
{
	Debug.WriteLine("ページがフレームに表示されました");

	// Navigate が実行された時のパラメータを表示しています
	var mp = (App.MyParam)e.Parameter;
	Debug.WriteLine("Title : " + mp.title);
	Debug.WriteLine("Type : " + mp.type);
}
関連する情報

XAML コードを横に長く表示させずに、属性毎に縦に表示させる設定




タグ:Windows8
posted by lightbox at 2013-05-10 15:57 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする

2013年05月03日


AppBar テンプレート / Win8 ストアアプリ(C#)

SkyDrive へ移動

ダウンロードしたテンプレートは、『C:\Users\ユーザー名\Documents\Visual Studio 2012\Templates\ProjectTemplates\Visual C#\Windows Store』に保存します。

Windows Store フォルダは最初は存在しないので作成します( 好きな名前のフォルダでも Visual Studio から利用できます )
ソースコード表示 仕様 ❶ Page.Resources で XAML 内で利用する文字列を定義 ❷ AppBar を XAML で定義 ❸ ボタンを左側3つ、右側2つ定義 ❹ それぞれのボタンにイベントを定義 ❺ 保存ボタンのイベントで、MessageDialog の利用サンプルを実装 ❻ MessageDialog のイベントを別のソースコードに定義( partial ) ❼ TextResource.cs に、StaticResource 用のクラスを定義 ❽ AutomationProperties を XAML とコードで使用して、ボタンの文字列を動的に変更
<Page.Resources>
	<local:TextResource
		x:Key="GlobalText"
		PageTitle="AppBar テンプレート"	/>
</Page.Resources>

<TextBlock
	HorizontalAlignment="Left"
	Height="61"
	Margin="76,60,0,0"
	TextWrapping="Wrap"
	Text="{Binding Source={StaticResource GlobalText},Path=PageTitle}"
	VerticalAlignment="Top"
	Width="1090"
	FontSize="40"
	FontWeight="Bold"
	FontFamily="Meiryo"
	/>
Page.Resources 内で定義している、local:TextResource は、XAML 内でクラスからインスタンスを作成する方法です。作成されたオブジェクトは、XAML 内で(ここでは) GlobalText の名前で参照されて利用されます。
( local は、『xmlns:local="using:LBOX_AppBar"』で定義 )

PageTitle="AppBar テンプレート" の記述では、TextResource クラスに定義されたプロパティ(PageTitle)にデータをセットしています。そして、利用側では Binding によって、オブジェクトの設定済みのプロパティを参照しています。
public class TextResource
{
	public string PageTitle { get; set; }
}

AutomationProperties

ボタンの文字列は、Style に定義した『StaticResource SaveAppBarButtonStyle』によって決定していますが、もともとのボタンのテキストでは無いので、AutomationProperties 経由で変更します。
<Button
	x:Name="SaveButton"
	AutomationProperties.Name="保存"
	Grid.Column="1"
	HorizontalAlignment="Stretch"
	VerticalAlignment="Stretch"
	Style="{StaticResource SaveAppBarButtonStyle}"
	Click="SaveButton_Click"
	/>

-----------------------------------------------------------------

// *************************************************
// メールボタンをロード時に、表示文字列を変更する
// *************************************************
private void MailButton_Loaded(object sender, RoutedEventArgs e)
{
	AutomationProperties.SetName(sender as Button, "メール");
}



posted by lightbox at 2013-05-03 08:23 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする

2013年04月19日


Windows ストアアプリの AppBar を作成してテストする

サンプルをコピーして実行すればできてしまいますが、『ブランクテンプレート』から、正攻法で作成する手順です。



StandardStyles.xaml の変更

Common フォルダにある StandardStyles.xaml を、Microsoft のサンプルの中にあるもので置き換えます。( 何故か、中身を変更しないと、AppBar のスタイルが使えないのですが、変更するよりコピーしたほうが確実なので )

実際問題として、Visual Studio 2012 のテンプレートやデザイナの出来は『良いものとは言えません』。製品版になる前から検証していますが、なにも問題は改良されていないので、がっかりしないようにして下さい。

Page のプロパティから『新規作成』

Visual Studio のデザイナ部分は、『Blend for Visual Studio』に力が入ってしまっていて、Visual Studio 本体のデザイナは、『とりあえずある』という程度です。なので、AppBar を追加するにしても、納得のいく形では出来上がりませんので注意して下さい。

本来ならば、デザイナに直接ドロップして Page のプロパティに設定すべき AppBar なのですが、デザイナから見えるのは Grid なので、そのままドロップすると Grid の中に定義されてしまって意味不明になります。

ですから、まずはテンプレートとして『プロパティ』の BottomAppBar プロパティの『新規作成』ボタンで挿入します。



▼ 新規作成すると以下のようになります



しかし、これでは何も設定されていないので、AppBar を選択した状態でデザイナ画面に移動して、AppBar をドロップします。



そうすると、やっとテンプレートらしきものが設定されるのですが、AppBar が二重になってしまうので、外側を削除します。



ボタンの追加

これでやっと、AppBar が作成されて、左右にバーが作成されている事になります。左側の StackPanel を選択してからデザイナ画面に移動して Button をドロップします。



ボタンが追加されたら、プロパティで余計な Content プロパティに設定されている表示用の文字列を削除し、Style プロパティでリソースに定義されている AppBar 用のボタンスタイルを設定します。
プロパティは、カテゴリで表示して『寄せ集め』から設定すると、いろいろ変更してテストしやすいです。
続けてイベントと他のコントロールを作成して動作確認 イベントは、プロパティウインドウの雷マークタブに移動して、該当するイベント欄をダブルクリックすると自動作成されます。
<Page
    x:Class="BlankApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BlankApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.BottomAppBar>
        <AppBar>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal">
                    <Button
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="Stretch"
                        Style="{StaticResource SettingsAppBarButtonStyle}"
                        Click="Button_Click_1"/>
                </StackPanel>
                <StackPanel 
                    Grid.Column="1"
                    HorizontalAlignment="Right"
                    Orientation="Horizontal"/>
            </Grid>
        </AppBar>
    </Page.BottomAppBar>

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <TextBox
            x:Name="MessageArea"
            HorizontalAlignment="Left"
            Height="116"
            Margin="88,68,0,0"
            TextWrapping="Wrap"
            VerticalAlignment="Top"
            Width="448"
            IsReadOnly="True"/>
    </Grid>
</Page>

以下は、メッセージ表示を行う『MessageDialog』ですが、応答するボタンを三つまで自由に作成する事ができます。

C# ならではの記述方法として、() => {処理}と、インスタンスを作成する場合に同時にプロパティを設定する {プロパティ=初期値[,プロパティ=初期値...]} を使っています。Id は、設定しておかないと、イベント内では何も入って来ないので注意して下さい

async と await については、こちらを参照して下さい。


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace BlankApp
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        private async void Button_Click_1(object sender, RoutedEventArgs e)
        {
            var messageDialog = new MessageDialog("メッセージ", "タイトル");

            messageDialog.Commands.Add(new UICommand("選択肢1", (command) =>
            {
                Debug.WriteLine(command.Label);
                Debug.WriteLine(command.Id);
                this.MessageArea.Text = command.Label + "\n" + command.Id;
            }) { Id = "idの型はobject" });

            messageDialog.Commands.Add(new UICommand("選択肢2", (command) =>
            {
                Debug.WriteLine(command.Label);
                Debug.WriteLine(command.Id);
                this.MessageArea.Text = command.Label + "\n" + command.Id;
            }) { Id = new Uri("http://winofsql.jp") });

            messageDialog.Commands.Add(new UICommand("アプリ終了", (command) =>
            {
                App.Current.Exit();
            }) { Id = 3 });

            messageDialog.DefaultCommandIndex = 1;

            await messageDialog.ShowAsync();

        }
    }
}




posted by lightbox at 2013-04-19 22:47 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする

2013年04月15日


Windows8 ストアアプリの StaticResource で使用されるテーマ色の定義場所

以下は、64ビットでの場所ですが、32ビットなら (x86) が無いだけだと思います。
C:\Program Files (x86)\Windows Kits\8.0\Include\WinRT\Xaml\Design\themeresources.xaml
ちなみに、Windows Phone は以下です。
C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Design\ThemeResources.xaml
C:\Program Files\Microsoft SDKs\Windows Phone\v7.1\Design\ThemeResources.xaml



posted by lightbox at 2013-04-15 23:41 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする

2012年12月03日


Windows8(C#) で Google にログインしてカレンダーの情報を扱う

Facebook もそうですが、ログイン処理には WebView を使ってユーザにはブラウザでログインするのと同じ処理をしてもらい、その結果で返ってくる URL 情報によって以降のアクセスで利用する『アクセストークン』を取得します。

プログラム作成に先だって、APIs Console で自分の API キー等を取得しておきます。( アプリは Client ID for web applications で取得 )





それぞれの API は API エクスプローラでテストする事ができます。例えばそのユーザが持ってるカレンダーの一覧は簡単に見る事ができます(右上の  OAuth 2.0 をオンにしてログインする必要があります )

アプリに登録する『リダイレクト場所』は、WEB 上の自分が管理する URL にします。このログインでは直接利用しませんが、実際はログイン後にユーザになんらかの情報を受け渡す為に使うといいと思います。

注意する事として、Google のログインページは JavaScript を使用しますので、Android や Windows Phone で同様の処理をする場合は、ブラウザの JavaScript を有効にしておく必要があります

LoginPage.xaml
<Page
	x:Class="Win8_C_Sharp_GoogleLogin.LoginPage"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:local="using:Win8_C_Sharp_GoogleLogin"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	mc:Ignorable="d">

	<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
		
		<!-- 戻るボタン -->
		<Button 
			x:Name="backButton" 
			Style="{StaticResource BackButtonStyle}"
			Click="backButton_Click"
			VerticalAlignment="Top" 
			Margin="101,52,0,0"/>

		<!-- 処理表示 -->
		<TextBlock 
			HorizontalAlignment="left" 
			Margin="208,52,0,0" 
			TextWrapping="Wrap" 
			Text="ログイン処理" 
			VerticalAlignment="Top" 
			Height="60" 
			Width="260" FontSize="48"/>
		
		<!-- ログイン認証WebView -->
		<WebView
		   x:Name="webView" 
			HorizontalAlignment="left" 
			Height="689" 
			Margin="101,136,0,-57" 
			VerticalAlignment="Top" 
			Width="1039" 
			LoadCompleted="webView_LoadComplete"/>

	</Grid>
</Page>

LoginPage.xaml
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using Windows.Storage;
using System.Diagnostics;
using System.Net.Http;
using Newtonsoft.Json.Linq;


namespace Win8_C_Sharp_GoogleLogin
{

	public sealed partial class LoginPage : Page
	{

		// ***************************************************
		// コンストラクタ
		// ***************************************************
		public LoginPage()
		{
			this.InitializeComponent();

			FacebookLogin();
		}

		// ***************************************************
		// WebView の表示
		// ***************************************************
		private void FacebookLogin()
		{
			// 対象となる URL を取得
			String url = App.gc.getLoginUrl();

			// 
			webView.Navigate(new Uri(url));

		}

		// ***************************************************
		// WebView がページを表示し終わった時の処理
		// ***************************************************
		private async void webView_LoadComplete(object sender, NavigationEventArgs e)
		{

			// URL を取得
			String token = e.Uri.ToString();

			if (token.IndexOf("code=") == 0)
			{
				// URL に含まれる仮のアクセストークンを取得する
				int cur = token.IndexOf("=");
				String code = token.Substring(cur+1);

				// アクセストークンを取得
				await App.gc.getAccessToken(code);

				// ユーザ情報を取得
				String info = await App.gc.getUserInfo();

				// このページを呼び出したメインページのフィールドにセット
				// 但し、メインページに戻る時は、GoBack を使ってはいけない
				((TextBox)App.mainPage.FindName("PostBody")).Text = info;
				
			}

		}


		// ***************************************************
		// メインページに戻る処理
		// ***************************************************
		private void backButton_Click(object sender, RoutedEventArgs e)
		{

			// 前のページに戻る「this.Frame.GoBack()」を実行するとMainPageの結果が消えてしまうため、
			// 一時変数を用意し、ページ遷移後に一時変数の中身をMainPageにセットする
			MainPage mp = App.mainPage;

			Frame rootFrame = Window.Current.Content as Frame;
			rootFrame.Content = App.mainPage;

		}

		protected override void OnNavigatedTo(NavigationEventArgs e)
		{
		}

	}
}

ここでは、前のページに戻る処理が重要です。サンプル等で使われている GoBack() では、元のページのインスタンスが新たに作成されるようなので、『ログイン』のようなダイアログ的な処理で使うととても都合が悪くなります。また、それに伴って、FindName で元のページのフィールドを参照する方法は重要です。

メインページのインスタンスは、起動時に App.xaml.cs で static の プロパティとして設定しておいて、アプリ全体からいつでもアクセスできるようにしておきます。

ログインや API の処理をするクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Windows.Data.Json;

namespace Win8_C_Sharp_GoogleLogin
{
	public class NGCalendar
	{

		// API Console 情報
		private String API_KEY = "";
		private String client_id = "";
		private String client_secret = "";

		// ログイン処理
		private String loginUrl = "https://accounts.google.com/o/oauth2/auth";
		private String type = "code";
		// redirect_uri は、API に登録した URL( ここでは Google Plus の プロフィールページでテスト )
		private String redirect_uri = "";
		// スコープ(権限)を設定 / 後で自分の情報を取得するのに、Gooogle Plus のスコープも設定
		private String scope = "https://www.googleapis.com/auth/calendar+https://www.googleapis.com/auth/calendar.readonly+https://www.googleapis.com/auth/plus.me";

		// 最終データ
		private String code = "";
		private String access_token = "";
		private String token_type = "";

		// Google API 取得先
		private String oauth2_url = "https://accounts.google.com/o/oauth2/token";
		private String g_calendar_list_url = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
		private String g_galendar_event_url = "https://www.googleapis.com/calendar/v3/calendars/[id]/events";

		// ***************************************************
		// GoogleログインURLを取得する
		// ***************************************************
		public String getLoginUrl()
		{
			String access_url = "";

			access_url = loginUrl;
			access_url += "?response_type=" + type;
			access_url += "&client_id=" + client_id;
			access_url += "&redirect_uri=" + redirect_uri;
			access_url += "&scope=" + scope;

			return access_url;

		}

		// ***************************************************
		// アクセストークンを取得する (POST)
		// ***************************************************
		public async Task<Boolean> getAccessToken(String code)
		{

			Boolean result = true;

			try
			{

				// Webにアクセスする
				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();
				requestMsg.Method = new HttpMethod("POST");


				String body = "";
				body = "code=" + code;
				body += "&grant_type=authorization_code";
				body += "&redirect_uri=" + redirect_uri;
				body += "&client_id=" + client_id;
				body += "&client_secret=" + client_secret;

				// 指定したURIを非同期で通信
				requestMsg.Content = new StringContent(body);
				requestMsg.Method = new HttpMethod("POST");
				requestMsg.RequestUri = new Uri(oauth2_url, UriKind.Absolute);
				requestMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 )
				String res = await response.Content.ReadAsStringAsync();

				// Json文字列を整形( Freamwork の JSON 処理 )
				JsonValue jv = JsonValue.Parse(res);

				// JSON よりアクセストークンとトークンのタイプを取得する
				this.access_token = jv.GetObject().GetNamedString("access_token");
				this.token_type = jv.GetObject().GetNamedString("token_type");

			}
			catch (Exception Err)
			{
				result = false;
			}

			return result;

		}


		// ***************************************************
		// カレンダー一覧を取得する (GET)
		// ▼ API エクスプローラでテストできます
		// https://developers.google.com/apis-explorer/#p/calendar/v3/calendar.calendarList.list
		// ***************************************************
		public async Task<String> getCalendarList()
		{
			try
			{
				String api_url = g_calendar_list_url + "?key=" + API_KEY;

				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();

				requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
				requestMsg.Method = new HttpMethod("GET");

				// ヘッダにアクセスする為の情報(アクセストークン)をセット
				// API エクスプローラで実際の内容を見る事ができます
				httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
				return await response.Content.ReadAsStringAsync();

			}
			catch (Exception Err)
			{
				throw;
			}
		}

		// ***************************************************
		// カレンダーに登録されたイベントを取得する ( GET )
		// ***************************************************
		public async Task<String> getCalendarEvent(String cid)
		{
			try
			{

				String api_url = g_galendar_event_url.Replace("[id]", Uri.EscapeDataString(cid)) + "?key=" + API_KEY;

				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();

				requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
				requestMsg.Method = new HttpMethod("GET");

				// ヘッダにアクセスする為の情報(アクセストークン)をセット
				httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
				return await response.Content.ReadAsStringAsync();
			}
			catch (Exception Err)
			{
				throw;
			}
		}

		// ***************************************************
		// Google Plus よりユーザー情報を取得する ( GET )
		// ***************************************************
		public async Task<String> getUserInfo()
		{
			try
			{

				String api_url = "https://www.googleapis.com/plus/v1/people/me?key=" + API_KEY;

				HttpClient httpClient = new HttpClient();
				HttpRequestMessage requestMsg = new HttpRequestMessage();

				requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
				requestMsg.Method = new HttpMethod("GET");

				// ヘッダにアクセスする為の情報(アクセストークン)をセット
				httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);

				// 呼び出し( 非同期 )
				var response = await httpClient.SendAsync(requestMsg);

				// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
				return await response.Content.ReadAsStringAsync();
			}
			catch (Exception Err)
			{
				throw;
			}
		}
	}
}

ここでは、JSON の処理を Framework で行っていますが、実際は Json.NET で行うととても便利です。Json.NET を使うと、ListBox 等の一覧処理が JSON 文字列からバインドまでを一気にできるようになります。

また、Windows8 では非同期処理でイベントを定義する必要がありません。async と await を駆使してコードを書くことができます。

関連する記事

Windows Phone(C#) のデータバインドを Json.NET を使って一行で実装する( しかも XML を JSON 変換して使う )

Windows8 の非同期処理(C#)
Windows8(C#) の WebView の LoadComplete で取得した URL 内のアクセストークンを Split で取得


posted by lightbox at 2012-12-03 12:34 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする

2012年11月19日


Windows8(C#)からFacebook へ画像をアップロードする。

▼ 実行画面

ログイン > 画像表示 > 画像投稿
( WEB カメラの画像も投稿できます )

SkyDrive へ移動


実行するには、Facebook での APIキーが必要になります。MainPage.xaml.cs の先頭に 『public String apiKey = "";』とありますので変更して下さい。
先にログインしてアクセストークンを取得する必要がありますが、サンプルコードに実装してあります。この処理で取得するのは2時間使用可能なアクセストークンになります。60日間に変更するには、手動でも可能なのでこちらを参考にして下さい(一旦60日に変更すると、この処理で取得しても60日になるようです)。

ファイルのアップロードは、通常の仕様通りですが、具体的なフォーマットをソースコードで知りたい場合は、『Windows Phone から Facebook に画像アップロード』を参照するか、実行時にローカルのWEBサーバーに対して実行してダンプしてみて下さい。AN HTTPD ならば、トレースログを有効にすると見る事ができます。

ファイルのアップロードには、画像データのバイト配列が必要になりますが、その読み込み部分もサンプルに実装されています。具体的には、StorageFile から IBuffer を作成して、 CryptographicBuffer.CopyToByteArray メソッドを実行するのが最も簡単です( 他にも方法はあります )

HTTP の仕様(マルチパートを使用する方法)に合わせてデータを作る方法としては、System.Net.Http(HttpClient の名前空間)に全て用意されていました。仕様をご存じな方であれば非常に簡単に実装できる事がお解りになると思います。

これらの処理は全て本来非同期ですが、Windows8 の非同期処理の実装方法によってイベント等を記述する必要がなくなっています。この実装の概要に関しては、『Windows8 の非同期処理(C#)』を参照して下さい。
try
{
	HttpClient httpClient = new HttpClient();
	httpClient.MaxResponseContentBufferSize = int.MaxValue;
	httpClient.DefaultRequestHeaders.ExpectContinue = false;

	MultipartFormDataContent form = new MultipartFormDataContent();
	StringContent sc = new StringContent(PostBody.Text);
	sc.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("post-data");
	sc.Headers.ContentDisposition.Name = "message";
	form.Add(sc, "message");

	var fileContent = new System.Net.Http.ByteArrayContent(data);
	fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");
	fileContent.Headers.ContentDisposition.FileName = "imagefile.jpg";
	fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
	fileContent.Headers.ContentDisposition.Name = "source";
	form.Add(fileContent, "source");

	HttpResponseMessage response = await httpClient.PostAsync(api_base_url+"me/photos?access_token=" + accessToken, form);
	String text = await response.Content.ReadAsStringAsync();

	Debug.WriteLine(text);

	MessageDialog msg = new MessageDialog("投稿が終了しました");

	msg.Commands.Add(new UICommand(
		"確認",
		new UICommandInvokedHandler(this.CommandInvokedHandler)));

	// Set the command that will be invoked by default
	msg.DefaultCommandIndex = 0;

	// Set the command to be invoked when escape is pressed
	msg.CancelCommandIndex = 1;

	// ダイアログ表示
	await msg.ShowAsync();

}
catch (Exception Err)
{
	throw;
}

参考

Uploading a file with Windows 8 WinRT -
How-To: Use the Graph API to Upload Photos to a user’s profile - Facebook開発者

関連する記事

Windows Phone から Facebook に画像アップロード
HTML(ローカル) を使用して Facebook へ画像をアップロードする
手動で Facebook API の 60日間の アクセストークンを取得する



タグ:Windows8 C# Facebook
posted by lightbox at 2012-11-19 19:16 | Win8 ストアアプリ | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり