Archive : 2009-07

JUL
30

ちょっと上海行ってきます

Published:2009-07-30 09:00:02 UTC

提携している研究室同士の研究発表会ということで、2日までの日程で上海行ってきます。まぁ要は、ちょっと海外行って自分の英語の出来なさに打ちのめされて来い、というイベント。ありがたい話です。

JUL
29

Mac始めました。

Published:2009-07-29 01:48:20 UTC
Mac

IMAGE_291 唐突ですが、Mac使いになりました。まさか自分がMacを使う日が来るとは思っていなかったので、自分でも驚いています(笑) SAをやらせて貰ったりと色々とお世話になっている大学の先生からMacBook KUROを貸していただけることになり、今、手元にあのMacが。研究室で同期や後輩が次々にMacに乗り換えているのを見て、「WPFの使えないデスクトップOSなんて使う奴の気が知れないわ~」とかのたまっていたのですが、いちいち画面が綺麗で統一感があり、Macも目的によれば良いかもしれないなーと思ったりしています。これまでずっとWindowsで、全くMacをつかったことがないので、まず操作からしてよくわからないことが多いのですが(GNOMEの方が百倍とっつきやすいです)、躓きながら慣れていこうかと思います。ただ、残念なことに、八月の頭にかけては全く触る暇がなさそうなので、ちょっとの間、放置になりそうではあります。しかしMacかー。どう使ったものか。流石にMacまで来てMonoでC#コードをゴリゴリ書くというのは考えていないのですけど(まぁMonoDevelopは入れるでしょうが)、今更Objective Cとやらを覚えるのもなー、とも思います。なるべく潰しのきかない言語は勉強したくないという思いがあるので、pureなCや、Pythonを書くのに使わせて貰おうかなと思います。

IMAGE_292 しかし貸して頂いているマシン、先生が新しいマシン(勿論Mac)を買ったので使わなくなったから、ということで貸して頂いているのですが、自分のラップトップ(VAIO)よりパワーがあるという。。自分のはVAIO Type SZ53Bをメモリ4GBに増設して使っているのですが、CPUはIntel Core 2 Duo 1.67GHzで、借りているMacBookはIntel Core 2 Duo 2GHz。。なんか、ブートキャンプでWindows 7 RC入れてWindows機としてVAIOをリプレースしたくなるのですが(笑)うーむ。

FILCO FKB108M/NB

IMAGE_294 そしてFILCOのキーボードもお借りしました。いやーこれまでキーボードにはそれほど拘らずにきたのですが、良いキーボードってあるんですね。なかなか打ち心地が滑らかで、変な突っかかりや重さがないので、軽快にタイピングをすることができます。この打ち心地を覚えてしまうと、もう安キーボードには戻れない気がするので、もう少しこのキーボードを試したら、秋葉原でRealforceとかと打ち較べてみて新しいキーボードを自分で買ってみようかと思います。

 

なんか最近、部屋がますますマニアックな雰囲気になってきてヤバいです。。どげんかせんといかん(ぇ

IMAGE_287

CardSafe/EはMVVMパターンに則って作るように心掛けたのですが、WPFと同じ感覚でSilverlightにMVVMパターンを適用しようとすると、色々と不都合が出てきて苦労させられました。Silverlightではオミットされている機能が結構あるので、そこに引っかかるとしばしば手戻りが発生します。このエントリではCardSafe/Eを書いていて気付いた点をとりあえず二点ほど。

SilverlightにはDataTemplate.Datatypeが存在しない

地味に痛いですこの仕様。ItemsControlから派生したコントロール(ListBoxなど)のItemをItemsSourceにセットしたINotifyPoropertyChangedを実装したコレクションから生成する際に、コレクションが列挙するインスタンスの型によってDataTemplateを切り替える場合、WPFではDataTemplate.Datatypeがあるので重宝するのですが、Silverlightでは3 RTWでもサポートされていません。DataTemplateSelectorもサポートされていないので、インスタンスの型や状態によってDataTemplateを切り替えることはできないようです。とりあえず逃げ道として自分はDataContextにセットされたインスタンスをみてContentを書き換えるロジックを書いたUserControlを用意しているのですが、面倒ですね。XAMLで宣言的に書きたいのでDataTemplate.Datatypeは是非サポートしてもらいたいものです。

TabcotrolのItemsSourceはTabItemのコレクションしか受け付けない

なんでー!?これまたあんまりな仕様。WPFではItemsControlから派生したコントロールのItemsSourceにINotifyPoropertyChangedを実装したコレクションをセットすると、その列挙する内容をListBoxItemやTabItemなど適当なコンテナに包んで表示してくれるので、あとはDataTemplateで表示内容を好きなようにカスタマイズしてやればよかったのですが、SilverlightのTabControlのItemsSourceはTabItemのコレクションしか受けてつけてくれないという。。これではTabItemに対応するViewModelのインスタンスをセットし、DataTemplateでViewを設定して表示内容をカスタマイズするというM-V-VMでよく知られたパターンが使えません。SilverlightでもListBoxではListBoxItem以外も受け付けてくれたのですけどねぇ。。ではどうするか。自分の場合はViewModelのコレクションをラップしてTabItemのコレクションとして公開するラッパークラスとConverterを用意することで凌ぎました。

ラッパークラスはこんな感じです。ViewModelのコレクションとViewModelからTabItemへの変換を行うFuncをコンストラクタの引数として取ります。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Controls;

namespace SharpLab.CredentialsLockerSilverlight.ViewModels {
	public class ReadOnlyObservableTabItemCollection<TViewModel, TViewModelCollection> : ICollection<TabItem>, INotifyCollectionChanged where TViewModelCollection : ICollection<TViewModel>, INotifyCollectionChanged {

		private TViewModelCollection _viewModels;
		private ObservableCollection<TabItem> _tabItems;
		private Func<TViewModel, TabItem> _converter;

		public ReadOnlyObservableTabItemCollection(TViewModelCollection viewModels, Func<TViewModel, TabItem> converter) {
			_converter = converter;
			_viewModels = viewModels;
			_tabItems = new ObservableCollection<TabItem>();

			foreach (var item in _viewModels) {
				_tabItems.Add(_converter(item));
			}

			_viewModels.CollectionChanged += new NotifyCollectionChangedEventHandler(_viewModels_CollectionChanged);

			_tabItems.CollectionChanged += new NotifyCollectionChangedEventHandler(_tabItems_CollectionChanged);
		}

		void _viewModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
			switch (e.Action) {
				case NotifyCollectionChangedAction.Add:
					_tabItems.Insert(e.NewStartingIndex, _converter((TViewModel)e.NewItems[0]));
					break;
				case NotifyCollectionChangedAction.Remove:
					_tabItems.RemoveAt(e.OldStartingIndex);
					break;
				case NotifyCollectionChangedAction.Replace:
					_tabItems.RemoveAt(e.OldStartingIndex);
					_tabItems.Insert(e.NewStartingIndex, _converter((TViewModel)e.NewItems[0]));
					break;
				case NotifyCollectionChangedAction.Reset:
					_tabItems.Clear();
					foreach (var item in _viewModels) {
						_tabItems.Add(_converter(item));
					}
					break;
			}
		}

		void _tabItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
			if (CollectionChanged != null) {
				CollectionChanged(this, e);
			}
		}


		public event NotifyCollectionChangedEventHandler CollectionChanged;

		#region ICollection<TabItem> メンバ

		public void Add(TabItem item) {
			throw new NotSupportedException();
		}

		public void Clear() {
			throw new NotSupportedException();
		}

		public bool Contains(TabItem item) {
			throw new NotImplementedException();
		}

		public void CopyTo(TabItem[] array, int arrayIndex) {
			throw new NotSupportedException();
		}

		public int Count {
			get {
				throw new NotImplementedException();
			}
		}

		public bool IsReadOnly {
			get {
				return true;
			}
		}

		public bool Remove(TabItem item) {
			throw new NotSupportedException();
		}

		#endregion

		#region IEnumerable<TabItem> メンバ

		public IEnumerator<TabItem> GetEnumerator() {
			foreach (var item in _tabItems) {
				yield return item;
			}
		}

		#endregion

		#region IEnumerable メンバ

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
			return GetEnumerator();
		}

		#endregion
	}
}

これを以下のようなConverterから利用します。

using System;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using System.Windows.Data;
using SharpLab.CredentialsLockerSilverlight.ViewModels;

namespace SharpLab.CredentialsLockerSilverlight.Views.Converter {
	public class CardVMCol2TabItemColConverter : IValueConverter{
		#region IValueConverter メンバ

		public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
			return new ReadOnlyObservableTabItemCollection<CardViewModel, ObservableCollection<CardViewModel>>((ObservableCollection<CardViewModel>)value,
				(each) => {
					var newTabItem = new TabItem() {
						DataContext = each,
						Header = new CardTabHeaderView(),
						Content = new SharpLab.CredentialsLockerSilverlight.Views.CardView()
					};
					return newTabItem;

				});
		}

		public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
			throw new NotImplementedException();
		}

		#endregion
	}
}

こうしてやることでTabControlのItemsSourceにViewModelのコレクションをバインドできるようになります。Converterは無理を通すのに便利な機能ですね。。

 ItemsSource="{Binding Path=CardViewModels, Converter={StaticResource CardVMCol2TabItemColConverter}}"
JUL
13

Silverlight 3のRTWがリリースされましたね。Silverlight Tools for Visual Studio 2008やExpression BlendのRCもリリースされています。version3から本気出すというMSの本領発揮とばかりに、結構便利になってきました。このエントリでは、自分が弄ってみて気づいたSilverlight 3 Betaからの変更点を書いてみたいと思います。

Silverlight 3 SDK Betaに含まれていたコントロールの一部がSilverlight Toolkitに移動

DataForm, DockPanel, WrapPanel, Expander, HeaderedContentControl, ViewboxがToolkitに移動したようです。それに伴って所属する名前空間が変わっているので注意が必要です。

Interactivity.dllの名前空間の変更

Expressionでは、3 MixPreviewからBehaviorというパターンがサポートされました。3 MixPreviewではプロジェクトでMicrosoft.Expression.Interactivity.dllというアセンブリを参照した上で、Behavior<T>クラスなどを継承して自分でBehaviorを作成するか、Microsoft Expression Community Galleryなどからダウンロードして使うという流れでした。今回リリースされたExpression 3RCでは、Microsoft.Expression.Interactivity.dllがSystem.Windows.Interactivity.dllと改名され、名前空間も変更されているので注意が必要です。この改名はBlend SDKの絡みでしょうか。また、BehaviorやTriggerActionの組み込み実装として、StoryBoardActionなどがMicrosoft.Expression.Interactions.dll内で提供されていますので、Microsoft Expression Community Galleryと共に活用していくよいでしょう。

DataGridのItemsSourceへのBindingが上手くいかない問題が修正

Silverlight 3 Betaの頃はDataGridのItemsSourceへのBindingが上手く動かないという問題がありました(DataGrid — binding to ItemsSource is broken : The Official Microsoft Silverlight Site)。今は修正されています。(これはむしろSilverlight Toolkitの話?)

Silverlight Tools for VS2008のSilverlightデザイナ削除

Silverlight 3 Tools for VS2008ではSilverlightデザイナが削除されています。まぁプレビューが上手く出来ない場合も多かったので、VS2010に期待ですね。今のうちにBlend 3に習熟しておきたいものです。

JUL
11

CardSafe/E公開!

Published:2009-07-11 22:49:49 UTC

CardSafeEverywhere 

ここ一か月ほど、週末やらに暇を見つけては作っていたアプリケーションが完成しました。CardSafe/Eというタイトルで、いわゆるパスワードマネージャなのですが、特長としてはMesh enabled webアプリケーションとして実装していることが挙げられます。Mesh enabled webアプリケーションとは、Microsoftが開発中のLive Frameworkを利用したアプリケーションの一形態です。Mesh enabled webアプリケーションは、Live Meshという、MicrosoftによるDropBox的なデータ同期サービス上に配置され、複数デバイス・サーバー間でのアプリケーションとそのデータの同期が自動的に行われるという特長があり、開発に用いる技術がAjaxやSilverlightであることから、デスクトップアプリケーションとして動かすだけでなく、Webブラウザ上の通常のWebアプリケーションとしても動かすことが出来ます。CardSafe/Eはこれを利用し、データ同期機能を持ったパスワードマネージャを実現しています。

利用方法

残念なことに、このLive Frameworkという技術はまだCTP版という扱いであり、通常のLive Mesh Beta版ではMesh enabled webアプリケーションであるCardSafe/Eは利用できません。CardSafe/Eを利用するには、https://developer.mesh-ctp.com/という開発者用のLive Meshを利用する必要があります。開発者用Live Meshは、テスト用ということもあり、Mesh enabled webアプリが使えるほかは、Live Mesh Beta版に比べて機能がかなり省かれており、CardSafe/E共々常用には向かないかと思います。それでもLive Frameworkを触ってみたいという場合は、

  1. Microsoft ConnectのAzure Services Invitation ProgramからLive ServicesのInvitation Codeを取得
  2. そのInvitation Codeを利用してAzure Services Developer Portalに登録
  3. 開発者用Live Meshにサインイン
  4. 開発者用Live MeshのDeviceタブからLive Framework Clientをインストール
  5. MeshにCardSafe/Eをインストール←このURLを踏んでMeshにCardSafe/Eをインストール

という手順になります。開発者用Live Meshへの登録手順などは、使ってみよう! Live Framework:第3回 はじめようLive Framework CTP|gihyo.jp … 技術評論社という記事が非常に分かりやすいので是非参照して進めてください。

new CloudApp()

ところで。このアプリケーションはnew CloudApp()というMicrosoftのコンテストに出しています。気に入って頂けた場合は、new CloudApp(): The Azure™ Services Platform Developer Challenge – Voteという投票ページでCardSafe/Eにご投票頂けると励みになります。CardSafe/Eに清き一票を!(ぇ

CardSafe/Eの公開ページ

CardSafe/E – SharpLab.