SQLの窓

2013年11月01日


VS2012 WPF(C#) : 『TKMP.DLL を使用したイベントによる非同期メール受信処理を Task(await) を使用して順次処理のように記述する』テンプレート

SkyDrive へ移動


Framework 4.5 では、Task<TResult> クラスによって非同期処理の結果を取得してあたかも同期処理のような記述を行う事ができるようになりましたが、既存の非同期処理をそのように書き換える為に、TaskCompletionSource<TResult> クラスを使用します。

単純に考えると、Task を戻り値とするメソッド内は全て管理されていて、その中で登録されたイベントは全て管理下に置かれるようです。イベントが終了するまで、メソッドが終わる事無く、TaskCompletionSource<TResult> クラスの TrySetResult( SetResult との違いは良く解りません )で、値をセットした時にメソッドが終了するように見えます。

こうする事によって、大きなメリットの一つとして、UI スレッドにふつうに戻って来て処理を行えるところであり、当然ループ内の一部として自然に行を追加しながら非同期を実現する事ができました



MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;
using TKMP.Net;
using System.IO;
using TKMP.Reader;
using System.Threading;
using System.Threading.Tasks;

namespace WPF_DataGrid_MailGet1 {
	public partial class MainWindow : Window {

		private MainViewModel mvm = new MainViewModel();
		private ImapClient client = null;

		// *********************************************
		// コンストラクタ
		// *********************************************
		public MainWindow() {
			InitializeComponent();

			this.dataGrid1.DataContext = mvm;
		}

		// 接続および、メールヘッダの取得
		private async void actButton_Click(object sender, RoutedEventArgs e) {

			mvm.mail_data.Clear();

			BasicImapLogon logon = new BasicImapLogon(this.userName.Text, this.password.Password);
			client = new ImapClient(logon, "imap.gmail.com", 993);
			client.AuthenticationProtocol = AuthenticationProtocols.SSL;

			if (!client.Connect()) {
				return;
			}

			// メールデータ一覧を格納するオブジェクト
			IMailData[] md = client.GetMailList();

			// データがありません
			if (md == null) {
				return;
			}

			// メールデータの数
			mailCount.Text = md.Length.ToString();

			// 読込み制限
			int maxCount = 20;
			int idx = 0;

			// 非同期で全て表示
			foreach (var data in md) {

				idx++;
				if (idx > maxCount) {
					break;
				}

				// Framework 4.5 : 値を返す非同期処理
				MailReader reader = await ReadBodyAnsync( data );

				// UI スレッドに戻って来ているので、特殊な処理は必要無い
				string from = "";
				string subject = "";
				string mdate = "";
				// ヘッダの一覧より、目的のヘッダを探す
				foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection) {

					if (headerdata.Name == "From") {
						from = headerdata.Data;
					}
					if (headerdata.Name == "Subject") {
						subject = headerdata.Data;
					}
					if (headerdata.Name == "Date") {
						mdate = headerdata.Data;
					}

				}

				// 行追加
				mvm.mail_data.Add(new ItemViewModel() {
					from = from,
					subject = subject,
					mdate = mdate
				});

			}
			// ソース的には、順次処理なので全てのデータ処理後のクローズ
			client.Close();

		}

		// *********************************************
		// 戻り値を返す事のできる非同期処理 【開始】
		// *********************************************
		private TaskCompletionSource<MailReader> tcs = null;
		private Task<MailReader> ReadBodyAnsync(IMailData MailData) {

			// 戻り値用のクラス
			tcs = new TaskCompletionSource<MailReader>();

			// 個別にイベント登録
			MailData.BodyLoaded += new EventHandler(MailData_event);
			// 非同期処理開始
			MailData.ReadBodyAnsync();

			return tcs.Task;
		}

		// 本来のイベント処理
		private void MailData_event(object sender, EventArgs e) {

			IMailData MailData = (IMailData)sender;

			// イベント削除
			MailData.BodyLoaded -= new EventHandler(MailData_event);

			// 本文無し( 本文が必要な場合は、false で、reader.MainText )
			MailReader reader = new MailReader(MailData.DataStream, true);

			// ****************************
			// 戻り値用のクラスの戻り値をセット
			// ****************************
			tcs.TrySetResult(reader);

		}
		// *********************************************
		// 戻り値を返す事のできる非同期処理 【終了】
		// *********************************************


		// ダブルクリック
		private void dataGrid1_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
			Debug.WriteLine(dataGrid1.SelectedIndex);

		}


	}
}

参考ページ

c# - Best way to convert callback-based async method to awaitable task - Stack Overflow
c# - TaskCompletionSource : When to use SetResult() versus TrySetResult(), etc - Stack Overflow

関連するページ

▼ このページの処理の元となった、通常のイベント非同期処理
WPF(C#) : 『DataGrid に、TKMP.DLL を使用して非同期にメールヘッダを受信する』 テンプレート



posted by lightbox at 2013-11-01 20:29 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2013年10月29日


Framework4(C#) : WebClient で Post と Get する汎用 static クラス

テストしたのは、Windows7 + Visual Studio 2010 + WPF アプリケーションです。

Web アクセスには、UrlEncode が必要になりますが、HttpUtility.UrlEncode はプロジェクトのプロパティで、『.NET Framework 4』にして System.Web を参照します。最初にプロジェクトを作成した場合、『.NET Framework 4 Client Profile』にセットされている場合があり、その場合  System.Web を参照できません。

HttpUtility.UrlEncode は、Windows Phone(OS 7.1) にもある事はあるのですが、エンコード結果が UTF-8 系列しか指定できないので、Encoding を指定する第二引数がありません。参照も、System.Windows の中の System.Net にあります。ですから、このクラスは Windows Phone(OS 7.1) では使用できません。

%エンコーディングの仕様が違いますが、WEB へ送信する場合は、Uri.EscapeDataString でも使用可能で、Twitter への投稿ではこちら(RFC 3986)が良いと思いますが、文字列は UTF-8 に変換されてエンコーディングされます。
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Web;

namespace winofsql {

	class Tool {

		public static string serverEncoding = "utf-8";

		// *********************************************
		// UTF-8 POST
		// *********************************************
		public static string Post(string url,
			Dictionary<string, string> param,
			UploadStringCompletedEventHandler UploadStringCompleted=null) {

			string result = "";

			try {
				WebClient webClient = new WebClient();
				webClient.Encoding = Encoding.GetEncoding(serverEncoding);

				if ( UploadStringCompleted != null ) {
					// 呼び出し側でラムダ式を使う事を想定した
					// イベント登録
					webClient.UploadStringCompleted += UploadStringCompleted;
				}

				webClient.Headers["Content-Type"] = "application/x-www-form-urlencoded";

				string data_string = "";

				foreach (KeyValuePair<string, string> kvp in param)
				{
					if (data_string != "")
					{
						data_string += "&";
					}
					data_string += kvp.Key + "=";

					// *******************************************************
					// プロジェクトのプロパティの対象フレームワークを 
					//『Framework 4』 にして System.Web を参照します
					// *******************************************************
					data_string += HttpUtility.UrlEncode(kvp.Value, Encoding.UTF8);
				}
				
				webClient.UploadStringAsync(new Uri(url), "POST", data_string);

			}
			catch (Exception Err) {
				result = "ERROR: " + Err.Message;
			}

			return result;

		}

		// *********************************************
		// エンコード指定 POST
		// *********************************************
		public static string Post(string url,
			string encoding,
			Dictionary<string, string> param,
			UploadStringCompletedEventHandler UploadStringCompleted=null) {

			string result = "";

			try {
				WebClient webClient = new WebClient();
				webClient.Encoding = Encoding.GetEncoding(serverEncoding);

				if ( UploadStringCompleted != null ) {
					// 呼び出し側でラムダ式を使う事を想定した
					// イベント登録
					webClient.UploadStringCompleted += UploadStringCompleted;
				}

				webClient.Headers["Content-Type"] = "application/x-www-form-urlencoded";

				string data_string = "";

				foreach (KeyValuePair<string, string> kvp in param)
				{
					if (data_string != "")
					{
						data_string += "&";
					}
					data_string += kvp.Key + "=";

					// *******************************************************
					// プロジェクトのプロパティの対象のフレームワークを 
					//『.NET Framework 4』 にして System.Web を参照します
					// *******************************************************
					data_string += HttpUtility.UrlEncode(kvp.Value, Encoding.GetEncoding(encoding));
				}
				
				webClient.UploadStringAsync(new Uri(url), "POST", data_string);

			}
			catch (Exception Err) {
				result = "ERROR: " + Err.Message;
			}

			return result;

		}

		// *********************************************
		// URL のみ呼び出し GET
		// *********************************************
		public static string Get(
			string url,
			DownloadStringCompletedEventHandler DownloadStringCompleted=null) {

			string result = "";

			try {
				WebClient webClient = new WebClient();
				webClient.Encoding = Encoding.GetEncoding(serverEncoding);

				if ( DownloadStringCompleted != null ) {
					// 呼び出し側でラムダ式を使う事を想定した
					// イベント登録
					webClient.DownloadStringCompleted += DownloadStringCompleted;
				}

				webClient.DownloadStringAsync(new Uri(url));

			}
			catch (Exception Err) {
				result = "ERROR: " + Err.Message;
			}

			return result;

		}

		// *********************************************
		// データ呼び出し( UTF-8 ) GET
		// *********************************************
		public static string Get(
			string url, 
			Dictionary<string, string> param,
			DownloadStringCompletedEventHandler DownloadStringCompleted=null) {

			string result = "";

			try
			{
				WebClient webClient = new WebClient();
				webClient.Encoding = Encoding.GetEncoding(serverEncoding);

				if (DownloadStringCompleted != null)
				{
					// 呼び出し側でラムダ式を使う事を想定した
					// イベント登録
					webClient.DownloadStringCompleted += DownloadStringCompleted;
				}

				string data_string = "";

				foreach (KeyValuePair<string, string> kvp in param)
				{
					if (data_string != "")
					{
						data_string += "&";
					}
					data_string += kvp.Key + "=";

					// *******************************************************
					// プロジェクトのプロパティの対象フレームワークを 
					//『Framework 4』 にして System.Web を参照します
					// *******************************************************
					data_string += HttpUtility.UrlEncode(kvp.Value, Encoding.UTF8);
				}

				webClient.DownloadStringAsync(new Uri(url + "?" + data_string));

			}
			catch (Exception Err)
			{
				result = "ERROR: " + Err.Message;
			}

			return result;

		}

		// *********************************************
		// データ呼び出し( エンコード指定 ) GET
		// *********************************************
		public static string Get(
			string url,
			string encoding,
			Dictionary<string, string> param,
			DownloadStringCompletedEventHandler DownloadStringCompleted=null) {

			string result = "";

			try
			{
				WebClient webClient = new WebClient();
				webClient.Encoding = Encoding.GetEncoding(serverEncoding);

				if (DownloadStringCompleted != null)
				{
					// 呼び出し側でラムダ式を使う事を想定した
					// イベント登録
					webClient.DownloadStringCompleted += DownloadStringCompleted;
				}

				string data_string = "";

				foreach (KeyValuePair<string, string> kvp in param)
				{
					if (data_string != "")
					{
						data_string += "&";
					}
					data_string += kvp.Key + "=";

					// *******************************************************
					// プロジェクトのプロパティの対象フレームワークを 
					//『Framework 4』 にして System.Web を参照します
					// *******************************************************
					data_string += HttpUtility.UrlEncode(kvp.Value, Encoding.GetEncoding(encoding));
				}

				webClient.DownloadStringAsync(new Uri(url + "?" + data_string));

			}
			catch (Exception Err)
			{
				result = "ERROR: " + Err.Message;
			}

			return result;

		}

	}
}


使用方法のサンプル
Tool.serverEncoding = "utf-8";
Tool.Post("http://student.xii.jp/lightbox/php_sample_1/log.php",
	"utf-8",
	new Dictionary<string, string>() { { "send", "ok" }, { "text", "日本語" } },
(object _sender, UploadStringCompletedEventArgs _e) =>
{
	// Error プロパティがセットされているとエラー
	if (_e.Error != null)
	{
		// エラー処理
	}
	// 正常な結果
	else
	{
		// 正常処理
	}
});

関連する記事

Framework4.5(C#)ストア : HttpClient で Post と Get する汎用 static クラス
Framework4(C#) : Windows Phone OS 7.1 : WebClient で Post と Get する汎用 static クラス
Android で Post と Get

いろいろな言語におけるバーセントエンコーディング





posted by lightbox at 2013-10-29 21:01 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2013年10月27日


WPF(C#) : 『DataGrid に、TKMP.DLL を使用して非同期にメールヘッダを受信する』 テンプレート

SkyDrive へ移動


メールサーバーは GMail の IMAP を使用してテストしています



MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;
using TKMP.Net;
using System.IO;
using TKMP.Reader;
using System.Threading;

namespace WPF_DataGrid1 {
	public partial class MainWindow : Window {

		private MainViewModel mvm = new MainViewModel();
		private SynchronizationContext sc = null;
		private ImapClient client = null;
		private int endCounter = 0;

		// *********************************************
		// コンストラクタ
		// *********************************************
		public MainWindow() {
			InitializeComponent();

			this.dataGrid1.DataContext = mvm;
		}

		// 接続および、メールヘッダの取得
		private void actButton_Click(object sender, RoutedEventArgs e) {

			mvm.mail_data.Clear();

			BasicImapLogon logon = new BasicImapLogon(this.userName.Text, this.password.Password );
			client = new ImapClient(logon, "imap.gmail.com", 993);
			client.AuthenticationProtocol = AuthenticationProtocols.SSL;

			if (!client.Connect()) {
				return;
			}

			// メールデータ一覧を格納するオブジェクト
			IMailData[] md = client.GetMailList();

			// データがありません
			if (md == null) {
				return;
			}

			// メールデータの数
			mailCount.Text = md.Length.ToString();

			// 読込み制限
			int maxCount = 20;
			int idx = 0;

			// 接続解除用
			endCounter = 0;

			// 非同期で全て表示
			foreach( var data in md ) {

				idx++;
				if (idx > maxCount) {
					break;
				}

				// 個別にイベント登録
				data.BodyLoaded += new EventHandler(MailData_BodyLoaded);
				// 非同期処理開始
				data.ReadBodyAnsync();

			}

		}

		private void MailData_BodyLoaded(object sender, EventArgs e) {

			IMailData MailData = (IMailData)sender;

			// 本文無し( 本文が必要な場合は、false で、reader.MainText )
			MailReader reader = new MailReader(MailData.DataStream, true);

			//Console.WriteLine(reader.MainText);

			// UI スレッドへの処理( この場合、post_state は null )
			sc.Post((object post_state) => {

				string from = "";
				string subject = "";
				string mdate = "";
				// ヘッダの一覧より、目的のヘッダを探す
				foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection) {

					if (headerdata.Name == "From") {
						from = headerdata.Data;
					}
					if (headerdata.Name == "Subject") {
						subject = headerdata.Data;
					}
					if (headerdata.Name == "Date") {
						mdate = headerdata.Data;
					}

				}

				// 行追加
				mvm.mail_data.Add(new ItemViewModel() {
					from = from,
					subject = subject,
					mdate = mdate
				});

			}, null);

			// イベント削除
			MailData.BodyLoaded -= new EventHandler(MailData_BodyLoaded);

			// 接続解除用
			endCounter++;
			if (endCounter == 20) {
				client.Close();
			}
		}

		// UI スレッドへの処理用
		private void Window_Loaded(object sender, RoutedEventArgs e) {
			sc = SynchronizationContext.Current;
		}

		// ダブルクリック
		private void dataGrid1_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
			Debug.WriteLine(dataGrid1.SelectedIndex);

		}


	}
}

非同期でのサーバーとの通信処理はすべてキューとして扱われるため、 前の処理が終了する前に次の要求を発行すると、要求順に順次処理が行われます
関連する記事 WPF(C#) : 『DataGrid に、バインド用クラスを使って自動的にカラムと行を生成する』 テンプレート
posted by lightbox at 2013-10-27 23:08 | VS(C#) | このブログの読者になる | 更新情報をチェックする

WPF(C#) : 『DataGrid に、バインド用クラスを使って自動的にカラムと行を生成する』 テンプレート

SkyDrive へ移動



※ Window の背景にイラスト画像を使用しています

DataGrid の重要なプロパティ
ItemsSource="{Binding mail_data}"
AutoGenerateColumns="True"
CanUserAddRows="false"
MainWindow.xaml
<Window x:Class="WPF_MailGet.MainWindow"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	mc:Ignorable="d"
	Title="MainWindow"
	Height="719"
	Width="805"
	BorderBrush="Black"
	BorderThickness="1">
	<Window.Background>
		<ImageBrush
			ImageSource="/WPF_MailGet;component/Images/back_001.jpg"
			Stretch="UniformToFill"
			TileMode="None" />
	</Window.Background>
	<!-- このウインドウのリソース -->
	<Window.Resources>

		<Style
			TargetType="{x:Type ListView}">
			<Setter
				Property="ItemContainerStyle">
				<Setter.Value>
					<Style
						TargetType="ListViewItem">
						<Setter
							Property="VerticalContentAlignment"
							Value="Top" />
					</Style>
				</Setter.Value>
			</Setter>
		</Style>
		
		<!-- 一覧データ 用の表示部品定義 -->
		<DataTemplate
			x:Key="ListFromTemplate">

			<StackPanel
				HorizontalAlignment="Left"
				Width="60">
				<TextBlock
					Text="{Binding from}"
					TextWrapping="Wrap"
					Padding="4" />
			</StackPanel>

		</DataTemplate>
		
		<DataTemplate
			x:Key="ListSubjectTemplate">
			
			<StackPanel
				Margin="0,0,0,17"
				Width="250">
				<Border
					BorderThickness="1"
					BorderBrush="Black"
					Padding="4"
					Height="50">
				<TextBlock
					Text="{Binding subject}"
					TextWrapping="Wrap" />
				</Border>
			</StackPanel>

		</DataTemplate>
	</Window.Resources>
	
	<Grid
		AllowDrop="True">
		<Grid.RowDefinitions>
			<RowDefinition
				Height="70*" />
			<RowDefinition
				Height="608*" />
		</Grid.RowDefinitions>
		
		<!--実行ボタン-->
		<Button
			Name="actButton"
			Content="データ表示"
			Height="35"
			HorizontalAlignment="Left"
			Margin="40,26,0,0"
			VerticalAlignment="Top"
			Width="154"
			Click="actButton_Click" />

		<!--一覧表示-->
		<DataGrid
			Grid.Row="1"
			Height="534"
			HorizontalAlignment="Left"
			Margin="40,0,0,0"
			Name="dataGrid1"
			VerticalAlignment="Top"
			Width="700"
			Background="#C5FFFFFF"
			MouseDoubleClick="dataGrid1_MouseDoubleClick"
			ItemsSource="{Binding mail_data}"
			AutoGenerateColumns="True"
			CanUserAddRows="false"
			IsReadOnly="True">
			<!--<DataGrid.Columns>
				<DataGridTemplateColumn
					Header="差出人"
					CellTemplate="{StaticResource ListFromTemplate}">
				</DataGridTemplateColumn>
				<DataGridTemplateColumn
					Header="件名"
					CellTemplate="{StaticResource ListSubjectTemplate}">
				</DataGridTemplateColumn>
			</DataGrid.Columns>-->
		</DataGrid>
		
	</Grid>
</Window>

コメント部分は、カラムをテンプレートで作成してカスタマイズする場合に使用します。

MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;

namespace WPF_MailGet {
	public partial class MainWindow : Window {

		private MainViewModel mvm = new MainViewModel();
		// *********************************************
		// コンストラクタ
		// *********************************************
		public MainWindow() {
			InitializeComponent();

			this.dataGrid1.DataContext = mvm;
		}

		private void actButton_Click(object sender, RoutedEventArgs e) {

			mvm.mail_data.Add(new ItemViewModel() {
				from = "Button@event.DataGrid.wpf",
				subject = "DataGrid は自動カラム作成が有効です",
				mdate = "2013/10/26 19:00:30",
			});
		}

		private void dataGrid1_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
			Debug.WriteLine(dataGrid1.SelectedIndex);

			mvm.mail_data.Add(new ItemViewModel() {
				from = "DoubleClick@event.DataGrid.wpf",
				subject = "CanUserAddRowsは、\n意図的に false にする必要があります",
				mdate = "2013/10/26 19:00:30",
			});

			mvm.mail_data[0].mdate = "0000/00/00";

		}

	}
}


MainViewModel.cs
using System;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace WPF_MailGet {

	// *********************************************
	// バインドする一覧データのを定義するクラス
	// *********************************************
	public class MainViewModel : MainBaseModel {
		// *****************************************************
		// コンストラクタ
		// *****************************************************
		public MainViewModel() {
			mail_data = new ObservableCollection<ItemViewModel>();
		}

		// *****************************************************
		// バインド用のコレクションのプロパティ
		// *****************************************************
		public ObservableCollection<ItemViewModel> mail_data { get; set; }

	}
}

ItemViewModel.cs
using System;
using System.ComponentModel;

namespace WPF_MailGet {
	// *********************************************
	// バインドする一覧データの構造を定義するクラス
	// *********************************************
	public class ItemViewModel : ItemBaseModel {

		// *********************************************
		// from エントリ
		// *********************************************
		private string _from;
		public string from {
			get { return _from; }
			set {
				SetAndNotifyString(GetName(() => from), ref _from, value);
			}
		}

		// *********************************************
		// subject エントリ
		// *********************************************
		private string _subject;
		public string subject {
			get { return _subject; }
			set {
				SetAndNotifyString(GetName(() => subject), ref _subject, value);
			}
		}

		// *********************************************
		// mdate エントリ
		// *********************************************
		private string _mdate;
		public string mdate {
			get { return _mdate; }
			set {
				SetAndNotifyString(GetName(() => mdate), ref _mdate, value);
			}
		}

	}
}



posted by lightbox at 2013-10-27 00:47 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2013年10月18日


VS2010(C#) : データベースを System.Data.Linq.DataContext で読み込んでからの LINQ

標準クエリ演算子の概要
標準クエリ演算子は、統合言語クエリ (LINQ) パターンを形成するメソッドです。 ほとんどの場合、そのメソッドの操作の対象はシーケンスです。シーケンスとは、IEnumerable インターフェイスまたは IQueryable インターフェイスを実装している型を持つオブジェクトのことです。 標準クエリ演算子には、クエリ機能が用意されています。たとえば、フィルター処理、射影、集計、並べ替えなどです。
データベースへのアクセスは SQL で実行しておいて、メモリにあるデータに対して LINQ を使用します。文字列の比較の為に、メソッドを一つ追加しています。 変数名に日本語を使用しているのは、テーブルの列定義が日本語の為です。変数を 英数字にするには、SELECT 構文で列に別名を付けて、格納用のクラスをその名前にします。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data.Odbc;
using System.Data.Linq;
using System.Data;

namespace DataContextTest {

	class Program {
		static void Main(string[] args) {

			OdbcConnection cn = null;
			string cs = "Driver={MySQL ODBC 5.2w Driver};" +
						"Server=localhost;" +
						"Database=lightbox;" +
						"Uid=root;" +
						"Pwd=password;";
			try {
				cn = new OdbcConnection(cs);
				// System.Data.Linq を参照
				DataContext context = new DataContext(cn);

				// select * from 社員マスタ で動作します
				string query = String.Format("select 社員コード,氏名 from 社員マスタ");

				// シーケンスとは、IEnumerable<T> インターフェイスまたは
				// IQueryable<T> インターフェイスを実装している型を持つオブジェクト
				IEnumerable<Syain> tables = context.ExecuteQuery<Syain>(query);

				var q =
				  from s in tables
				  where comp(true,s.社員コード,"0005")
				  select s;

				foreach (var s in q) {
					Console.Write("{0}, {1}\n", s.社員コード, s.氏名);
				}

			}
			catch (Exception ex) {
				Console.WriteLine(ex.Message);
			}

			if (cn.State == ConnectionState.Open) {
				cn.Close();
				cn.Dispose();
			}

			Console.ReadLine();
		}

		// 文字列比較用
		public static bool comp(bool type,string a, string b) {

			if (a == b) {
				return true;
			}

			if (a.CompareTo(b) < 0) {
				return !type;
			}
			else {
				return type;
			}
		}

		private class Syain {
			public string @社員コード { get; set; }
			public string @氏名 { get; set; }
		}
	}
}




posted by lightbox at 2013-10-18 22:42 | VS(C#) | このブログの読者になる | 更新情報をチェックする

WPF(C#) : ExecuteQuery<T> を使って、DataGrid に自動的に select 構文の結果を表示する



※ System.Data.Linq を参照して下さい

元々は、Windows Phone のテンプレートにあるバインド方法ですが、DataGrid にある AutoGenerateColumns プロパティはデフォルトで ON です。そもそも、こういう目的に使えるようにできています。

テーブル定義用のクラスは、ObservableCollection<T> でまとめられる必要があるので、ExecuteQuery の結果を使って ObservableCollection<T> を作り直して DataContext に設定します。その際、ItemsSource は、{Binding} である必要があります。

※ 社員マスタの列はもっとたくさんあります

MainWindow.xaml
<Window x:Class="WpfDataGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
		<DataGrid
			Height="217"
			HorizontalAlignment="Left"
			Margin="54,56,0,0"
			Name="dataGrid1"
			VerticalAlignment="Top"
			Width="399"
			AutoGenerateColumns="True"
			ItemsSource="{Binding}" />

		<Button
			Content="Button"
			Height="24"
			HorizontalAlignment="Left"
			Margin="55,17,0,0"
			Name="button1"
			VerticalAlignment="Top"
			Width="113"
			Click="button1_Click" />
	</Grid>
</Window>


MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data;
using System.Data.Odbc;
using System.Diagnostics;
using System.Data.Linq;
using System.Collections.ObjectModel;

namespace WpfDataGrid
{

    public partial class MainWindow : Window
    {
        private OdbcConnection cn = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        private class Syain
        {
            public string @社員コード { get; set; }
            public string @氏名 { get; set; }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            string cs = "Driver={MySQL ODBC 5.2 Unicode Driver};" +
			            "Server=localhost;" +
			            "Database=lightbox;" +
			            "Uid=root;" + 
			            "Pwd=password;";

            string query = String.Format("select 社員コード,氏名 from 社員マスタ where 社員コード >= '{0}'", "0005");

            try {
                cn = new OdbcConnection(cs);
                DataContext context = new DataContext(cn);
                this.dataGrid1.DataContext = 
                    new ObservableCollection<Syain>(
                        context.ExecuteQuery<Syain>(query)
                    );
            }
            catch( Exception ex ) {
                Debug.WriteLine(ex.Message);
            }

            if ( cn.State == ConnectionState.Open ) {
                cn.Close();
                cn.Dispose();
            }

        }
    }
}

ただ、VS2010 では、バグがあるようで、行が1行多く作成されてしまいます。VS2012 ではうまく行くんですが・・・。それと、ExecuteQuery の変数バインド機能は動作しませんでした。

CanUserAddRowsを 意図的に false にする必要があります。( デフォルトが true でした )。後、セル内の編集が必要無いのであれば、IsReadOnly を true にしてもかまいません。


posted by lightbox at 2013-10-18 03:04 | VS(C#) | このブログの読者になる | 更新情報をチェックする
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 終わり