SQLの窓

2012年10月27日


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

以下の画像はこのブログの index20.rdf を表示しています



SkyDrive に移動


サンプルは、2ページ仕様で表示していますが、1ページ目の内容を再度表示しているだけです。重要なのは、Json.NET の使い方と、その為のバインド用のクラスの作成方法です。

※ データは NAVER まとめのデータを利用してテストしています
※ 結果をアプリからの投稿用の『超簡易掲示板』を使用して JSON 文字列を書き込んでいます

Windows Phone まとめリンク

Windows Phone

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using System.Diagnostics;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Xml.Linq;
using Microsoft.Phone.Tasks;

namespace DataBound_ListBox_JSON
{
	public partial class MainPage : PhoneApplicationPage
	{
		// コンストラクター
		public MainPage()
		{
			InitializeComponent();

			// ListBox コントロールのデータ コンテキストをサンプル データに設定します
			DataContext = App.ViewModel;
			this.Loaded += new RoutedEventHandler(MainPage_Loaded);

			App.mainPage = this;

		}

		private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
		{
			if (e.Error != null)
			{
				Deployment.Current.Dispatcher.BeginInvoke(() =>
				{
					Debug.WriteLine(e.Error.Message);
				});
			}
			else
			{
				JObject RSS = null;
				JArray jsonItems = null;
				string json_string = null;
				int rowMax = 0;

				// XML 文字列を dom に変換
				XDocument dom = XDocument.Parse(e.Result);

				// dom を JSON 文字列に変換
				json_string = JsonConvert.SerializeXNode(dom.FirstNode);

				// JSON 文字列を JSON 表現可能な JObject に変換
				RSS = JObject.Parse(json_string);

				// 対象となる item の数を得る
				jsonItems = (JArray)RSS["rss"]["channel"]["item"];

				// **********************************
				// ここからテスト確認用はじまり
				// **********************************
				rowMax = jsonItems.Count;
				// トップから一覧表示
				for (int i = 0; i < rowMax; i++)
				{
					Debug.WriteLine(RSS["rss"]["channel"]["item"][i]["title"]);
					Debug.WriteLine(RSS["rss"]["channel"]["item"][i]["description"]);
					Debug.WriteLine(RSS["rss"]["channel"]["item"][i]["link"]);
				}

				Debug.WriteLine("----------------------------------");

				// 必要部分のみ(item)を JSON 文字列に戻す
				json_string = JsonConvert.SerializeObject(jsonItems);  // 必要なのはここだけ
				json_string = "{ item: " + json_string + "}";

				RSS = JObject.Parse(json_string);

				// 対象のみ
				for (int i = 0; i < rowMax; i++)
				{
					Debug.WriteLine(RSS["item"][i]["title"]);
					Debug.WriteLine(RSS["item"][i]["description"]);
					Debug.WriteLine(RSS["item"][i]["link"]);
				}

				WebClientPost.LogPost("http://localhost/php_json/log.php", json_string);
				// **********************************
				// ここまでテスト確認用の終わり
				// **********************************


				// **********************************
				// バインドは以下の一行で完了
				// **********************************
				App.ViewModel = JsonConvert.DeserializeObject<MainViewModel>(json_string);
				// データコンテキスト設定
				DataContext = App.ViewModel;


				// ロード済のフラグをセット
				App.ViewModel.IsDataLoaded = true;
			}
		}

		// ListBox で変更された選択項目を処理します
		private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			// 選択されたインデックスが -1 の場合 (選択されていない場合) は何も行いません
			if (MainListBox.SelectedIndex == -1)
				return;

			// 新しいページに移動します
			NavigationService.Navigate(
				new Uri("/DetailsPage.xaml?selectedItem=" + MainListBox.SelectedIndex, UriKind.Relative)
				);

			// 選択されたインデックスを -1 (選択されていない) にリセットします
			MainListBox.SelectedIndex = -1;
		}

		// ViewModel Items のデータを読み込みます
		private void MainPage_Loaded(object sender, RoutedEventArgs e)
		{
			if (!App.ViewModel.IsDataLoaded)
			{
				LoadData();
			}
		}

		public void LoadData()
		{

			if (App.ViewModel.IsDataLoaded)
			{
				App.ViewModel.item.Clear();
			}

			WebClient webClient = new WebClient();
			webClient.DownloadStringCompleted +=
				new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
			// 外部サービスから文字列を取得
			webClient.DownloadStringAsync(new System.Uri("http://matome.naver.jp/feed/hot"));
		}

	}
}
関連する記事

PHP による『超簡易掲示板』 / アブリケーションからの POST 検証用


タグ:JSON
posted by lightbox at 2012-10-27 23:29 | Windows Phone | このブログの読者になる | 更新情報をチェックする

2012年10月21日


WindowsPhone からの単純なインターネット投稿

SkyDrive へ移動

WebClientPost.cs

WebClientPost.LogPost("http://localhost/lightbox/test/log.php", json_string);

PHP による『超簡易掲示板』 / アブリケーションからの POST 検証用 を使用して外部ログとして利用できます。( Debug.WriteLine だととても長い文字列を簡単に取得できません )

using System;
using System.Net;
using System.Windows;

public class WebClientPost
{
	public static void LogPost(string url,string value){

		WebClient HttpClient = new WebClient();

		// ダウンロード完了後に呼び出されるイベントハンドラを設定
		HttpClient.UploadStringCompleted += new UploadStringCompletedEventHandler(HttpPostCompleted);

		// POST 用 Http ヘッダの設定
		HttpClient.Headers["Content-Type"] = "application/x-www-form-urlencoded";

		string data_string = "send=send&text=" + Uri.EscapeDataString(value);
		HttpClient.UploadStringAsync(new Uri(url), "POST", data_string);

	}

	static void HttpPostCompleted(object sender, UploadStringCompletedEventArgs e)
	{
		if (e.Error == null)
		{
			MessageBox.Show("送信しました");
		}
		else
		{
			MessageBox.Show("通信エラーが発生しました。\r\n" + e.Error.Message);
		}
	}

}

関連する記事

PHP による『超簡易掲示板』 / アブリケーションからの POST 検証用


posted by lightbox at 2012-10-21 19:45 | Windows Phone | このブログの読者になる | 更新情報をチェックする

Json.NET を使って、XML データを JSON に変換して利用する / Windows Phone(C#)

using System.Xml.Linq が必要です。このサンプルでは、JObject を作成してループ処理していますが、実際は item 以下の JSON 文字列を作成して、JsonConvert.DeserializeObject を使って C# のクラスのインスタンスを作成します。

その クラスのインスタンスを DataContext に設定してバインドする事によって自動的に ListBox の表示が可能になります。
JObject RSS = null;
JArray jsonItems = null;
string json_string = null;
int rowMax = 0;

// XML 文字列を dom に変換
XDocument dom = XDocument.Parse(e.Result);

// dom を JSON 文字列に変換
json_string = JsonConvert.SerializeXNode(dom.FirstNode);

// JSON 文字列を JSON 表現可能な JObject に変換
RSS = JObject.Parse(json_string);

// 対象となる item の数を得る
jsonItems = (JArray)RSS["rss"]["channel"]["item"];
rowMax = jsonItems.Count;
// トップから一覧表示
for (int i = 0; i < rowMax; i++)
{
	Debug.WriteLine(RSS["rss"]["channel"]["item"][i]["title"]);
	Debug.WriteLine(RSS["rss"]["channel"]["item"][i]["description"]);
	Debug.WriteLine(RSS["rss"]["channel"]["item"][i]["link"]);
}

Debug.WriteLine("----------------------------------");

// 必要部分のみ(item)を JSON 文字列に戻す
json_string = JsonConvert.SerializeObject(jsonItems);
json_string = "{ item: " + json_string + "}";

RSS = JObject.Parse(json_string);

// 対象のみ
for (int i = 0; i < rowMax; i++)
{
	Debug.WriteLine(RSS["item"][i]["title"]);
	Debug.WriteLine(RSS["item"][i]["description"]);
	Debug.WriteLine(RSS["item"][i]["link"]);
}



タグ:JSON
posted by lightbox at 2012-10-21 01:36 | Windows Phone | このブログの読者になる | 更新情報をチェックする
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 ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり