犬情報
犬を各種ブログ(Blog)から一括検索します。
トップ > project > project - 人気ブログ(Blog)検索結果詳細 (2008年12月3日 5時)
【.NET】"愛々,123".IndexOf(",")が不正な結果を返す
説明
文字によって、string.IndexOf()が不正な結果を返却します。.NET Framework 1.1ではこの現象は起きません。
https://connect.microsoft.com/VisualStudioJapan/feedback/ViewFeedback.aspx?FeedbackID=381451
先月、話題になっていた愛々ですが、ここがネタ元だったのかしら?
作者:art55
更新日:2008年12月3日 8時21分
【Silverlight】DataGridに表示されてるデータの件数

Source and Project
かずきのBlog様のエントリーを見ていてびっくりしたのですが、
SilverlightのDataGridには行の数を取得するプロパティやメソッドが存在しません。
そもそもItemsプロパティが存在しません。
WPFの場合、Itemsプロパティが存在し、Itemsに直接アイテムを挿入したり、
ItemsSource経由でItemsのアイテムを構築したりできたりするわけですが、
それがSilverlightではできないようです。
その弊害で行の数がコントロールから取得できない状況になっているようです。
まあ、ItemsSourceがIEnumerableなので素直にそこから数を取得するれば言いわけです。
ということでコードを実装すると
public static class DataGridUtil
{
...
public static int ItemsCount(this DataGrid dataGrid)
{
if (dataGrid.ItemsSource == null)
return 0;
if (dataGrid.ItemsSource is ICollection)
return ((ICollection) dataGrid.ItemsSource).Count;
return dataGrid.ItemsSource.Cast<object>().Count();
}
}
ちょっとしたテクニックでICollectionにキャスト可能であれば、
そのオブジェクトはCountableなので、そのままCountを取得可能です。
あとはLinqでちょちょちょです。Linq素敵です。
また、また、トンチ絵を描くと

IEnumerableやIColletionなどの継承関係はこのようになっています。
IColletionにキャスト可能であればCountが取得できます。

IEnumerableからIEnumerable<T>に変更できれば
IEnumerable<T>.Count()メソッドが使用できますので、
IEnumerableのコレクションをひとつひとつobjectにキャストし
IEnumerable<object>に変更したうえ、Count()を取得すればカウントが取得できます。
だらだら書きましたが、これはあくまでDataGridというControlからItemの数を取得するプロセスです。
アイテムを挿入する入口がItemsSourceしかないので、
おおもとのオブジェクトから数を取得すれば良いだけですよね。
きちんと調べてませんが、DataGrid自身にWhereな処理系(アイテムの数を絞る処理)が
実装されていないようなので、どこからアイテムの数を取得しても大丈夫そうです(たぶん)
では、蛇足へ向かいます。
文字通り「DataGridに表示されてるデータの件数」方法は?
どういう意味かというと画面上に表示されているアイテムの数を取得する方法です。
たとえば100件データを突っ込んでも、それがすべて画面上に表示されているわけではありません。
表示に必要な、たとえば画面上に7件しか表示範囲がない場合は
その7件を取得したい場合はどうすればいいでしょうか?
実装してみまいした。
public static class DataGridUtil
{
public static int VisibleRowsCount(this DataGrid dataGrid)
{
var rowsPresenters = dataGrid.Find("RowsPresenter").Cast<DataGridRowsPresenter>().ToList();
return rowsPresenters.Count() == 0 ? 0 :
rowsPresenters[0].Children.Where(item => item.Visibility == Visibility.Visible).Count();
}
public static int ItemsCount(this DataGrid dataGrid)
{
if (dataGrid.ItemsSource == null)
return 0;
if (dataGrid.ItemsSource is ICollection)
return ((ICollection) dataGrid.ItemsSource).Count;
return dataGrid.ItemsSource.Cast<object>().Count();
}
}
--------------------------
public static class VisualTreeUtil
{
private delegate bool FindExecute(DependencyObject child);
public static IList<DependencyObject> Find(this DependencyObject control, string name)
{
IList<DependencyObject> result = new List<DependencyObject>();
Find<FrameworkElement>(control, result,
child => child is FrameworkElement && ((FrameworkElement)child).Name == name);
return result;
}
public static IList<T> Find<T>(this DependencyObject control)
where T : DependencyObject
{
IList<DependencyObject> result = new List<DependencyObject>();
Find<T>(control, result, child => child is T);
return result.Cast<T>().ToList();
}
private static DependencyObject Find<T>(this DependencyObject control, ICollection<DependencyObject> result, FindExecute findExecute)
where T : DependencyObject
{
int count = VisualTreeHelper.GetChildrenCount(control);
for (int i = 0; i < count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(control, i);
if (findExecute(child))
return child;
DependencyObject returnValue = Find<T>(child, result, findExecute);
if (returnValue != null)
result.Add(returnValue);
}
return null;
}
}
----------------------------------
DataGridのクラスの属性を見ると
[TemplatePartAttribute(Name = "ColumnHeadersPresenter", Type = typeof(DataGridColumnHeadersPresenter))]
[TemplatePartAttribute(Name = "HorizontalScrollbar", Type = typeof(ScrollBar))]
[TemplatePartAttribute(Name = "VerticalScrollbar", Type = typeof(ScrollBar))]
[TemplatePartAttribute(Name = "RowsPresenter", Type = typeof(DataGridRowsPresenter))]
[TemplatePartAttribute(Name = "FrozenColumnScrollBarSpacer", Type = typeof(FrameworkElement))]
public class DataGrid : Control
と、なっていますので、ControlTemplate内にRowsPresenterという名前で
DataGridRowsPresenterが定義されていると予想されます。
しかし、しかし、SliverlightにはControlTempate.FindName()が存在しません。
ガーンです。
ということでVisualTree内から名前を探すようにしてみました。
ControlTemplateをいじられるとお釈迦になるような気もしなくもないのですが、
DataGridUtilクラスとVisualTreeUtilクラスで
現在、表示されているアイテムが取得可能です。
ポイントはVisibility.Visibleなアイテムのみを取得するというところですね。
デフォルトDataGridのItemsPanelはヴァーチャルモードで動いているようなので
表示されているアイテムと選択されているアイテムだけが
DataGridRowsPresenterのChildとしてVisualTree上に構築されています。
その中でVisibility.Visibleになっているものが表示されているという事になります。
ええ。たぶんね。
ということで今回作ってみたサイトの紹介です。実装はSource and Projectで。
まず、初期画面。

アイテムを追加してみて、数をカウントしてみます。
すべてのアイテムが表示されているので、
内部のアイテムの数と表示されているアイテムの数が同値です。

さらにアイテムを追加して、表示範囲を超えるようにしてみました。
内部のアイテムの数と表示されているアイテムの数が違うことがわかります。
5件しか見えていないようにみえますが、最下位部分にアイテムがあります。
なので6件です。

おそらくSilverlightのソースをアップするのは初めてだと思いますが
それもそのはず、Silverlight2がリリースされてからSilverlight2をいじったのは
今回が初めてです。
WPFとほとんど一緒ですが・・・・
えー。えーって結構、WPFに比べて機能が縮小されている部分があり驚かされます。
そうそう、ツールボックスからプレビューにドラックアンドドロップできないんですね。
その代りツールボックス中のコントロールをダブルクリックすると
XAMLにタグが追加される機能があり、ちゃんと名前空間も補完してくれます。
普段、XMALを手書きしているので、こっちのほうが嬉しいですね。
うん。
Source and Project
作者:art55
更新日:2008年12月3日 8時5分
【WPFセミナー】Visual Studio 2008 ではじめる WPF プログラミング
Visual Studio 2008 ではじめる WPF プログラミング
〜はじめての User Experience 〜
概要
新しくリリースされた Visual Studio 2008 では、さまざまな新しい新機能、新テクノロジを搭載し登場しています。本セミナーでは Visual Studio 2008 の新しい機能についての説明を交えながら、新しい UI テクノロジである Windows Presentation Foundation (通称:WPF) によるプログラミングについて解説します。.NET Framework 3.0 から登場した新しい UI テクノロジである WPF は、リッチでインタラクティブなプレゼンテーションを持つアプリケーションの容易な開発を可能にします。WPF はどのようなテクノロジなのか、WPF の開発はどのような開発を行うのかも合わせてご説明いたします。
(セミナーでは C# を利用して実際にコードを書くセッションが含まれますが、.NET を使用した開発経験のある方であれば、C# 未経験の方でも抵抗なく受講いただけます。)
http://www.microsoft.com/japan/mscorp/mic/seminar/hrd_wpf.mspx
無料でWPFのハンズオンセミナーを受けられるというのはもの凄く幸せな事だと思います。
もしWPFのスキルが必要な方が周りにいるなら、勧めましょ!!
WPFが扱える技術者増やしましょ!
作者:art55
更新日:2008年12月3日 2時46分
【Silverlightセミナー】Silverlight 2 プログラミング セミナー
Silverlight 2 プログラミング セミナー
概要
リッチでインタラクティブな User Experience を持つ UI の作成やメディア配信などが行えるテクノロジ「Silverlight 2」のプログラミング方法について体系的に学ぶことができます。本セミナーでは Visual Studio 2008 と Expression を利用し、Silverlight2 のテクノロジ、そしてコンテンツ作成方法、開発方法についての基礎的な知識を得ることを目標とします。
http://www.microsoft.com/japan/mscorp/mic/seminar/silverlight2.mspx
受付が近日公開らしいです!
作者:art55
更新日:2008年12月3日 2時41分
【WPF】PropertyChangedEventManager詳説のための準備
「PropertyChangedEventManager詳説」とタイトルで宣言してしまいましたが
いってみただけーで終わらないように努力したいと思います。
PropertyChangedEventManagerのクラスの関係を見てみました。
結構シンプルですね。ビックリです。

PropertyChangedEventManagerはWeakEventManagerの実装の一つです。
他にもWeakEventManagerを継承しているクラスのいくつかあり、
ちょこっと探すだけでも下記のようなクラスが見つかります。
CurrentChangingEventManager
DataChangedEventManager
DispatcherShutdownStartedEventManager
InheritanceContextChangedEventManager
LostFocusEventManager
PropertyChangedEventManager
ValueChangedEventManager
上記のようにいろいろあるようですが、
WPFフレームワークを利用するようなコードをコーディングしても
これらのEventManagerを意識する事はほとんどありませんが
調べてみるのは面白そうです。
ええ。調べてみようと思います。
作者:art55
更新日:2008年12月1日 0時34分
【雑記】あなたのシンボルCPUは「Core2 Quad Processor」です。
OPC Diary様にCPU占いというのが紹介されていたので
早速、占ってもらいました。
私は「Core2 Quad Processor」でした。
そうそう。先日衝動買いしたCPUもCore2Quadでした。
Core i7と迷ったのですが、他のパーツとの組み合わせを考えたときに
どーしてもCore i7では予算がふくれあがるので・・・もうちょっと安くってからで−。
参考
CPU占い
http://zigsow.jp/cpu/
作者:art55
更新日:2008年11月30日 10時47分
【.NET】.NET Framework Libraries. Available Source Code Components
2,3日前に下記のサイトを見ると
.NET Framework Libraries
http://referencesource.microsoft.com/netframework.aspx
すべてのプロダクトがダウンロードのリンクが無くなっていて
ダウンロード不可になっていることを確認しましたが
先ほどのぞいてみると
・NET Version 8.0
・FX1434 Version 1.0
・dotnetfx35SP1_3053 Version 1.1
の3つがダウンロード可能な状態に戻ったようです。
さらに
・dotnetfx35SP1_3053 Version 1.3
と言うのが追加されているようなので早くダウンロード可能にならないかな〜と
思う今日この頃です。
Configuring Visual Studio for Debugging
http://referencesource.microsoft.com/serversetup.aspx
いろいろなサイトで紹介されている方法ですが、まあ公式サイトが一番参考になるかなと思い、紹介しておきます。
作者:art55
更新日:2008年11月30日 9時53分
【Book】細部切れわたる「Pro C# 2008 and the .NET 3.5 Platform」

Pro C# 2008 and the .NET 3.5 Platform (Windows.Net)
Andrew Troelsen
C#3.0と.NET Frameworkに関してカバーしている範囲が広いです。
作者:art55
更新日:2008年11月29日 17時43分
【Book】手の届く範囲に置いておきたくなる「C# 3.0 in a Nutshell」

C# 3.0 in a Nutshell (In a Nutshell (O¥'Reilly))
Joseph Albahari,Ben Albahari
洋書ですけど、すごくいい感じです。
まとめ方や表現方法がすばらしいです。
作者:art55
更新日:2008年11月29日 3時4分
【WPF】Performance Profiling Tools for WPF
Performance Profiling Tools for WPF
http://windowsclient.net/wpf/perf/wpf-perf-tool.aspx
What's New for Performance Profiling Tools for WPF
The WPFPerf tool comprises of a suite of performance profiling tools that allow you to analyze the run-time behavior of your WPF application and point to potential performance bottlenecks. We've given WPFPerf a facelift, added some exciting new features, and fixed a few bugs. Read below to learn about some of the improvements in this update.
しっかり調べようと思っただけーの状態になっているので
時間を作って調べたいと本当です。本当です。本当です。
作者:art55
更新日:2008年11月29日 2時59分
【散財】PCパーツを買ってしまう。
サーバ用にPCパーツを購入してしまいました。
完全な衝動買いです。
サーバ用に自作というの何だが矛盾しているような気もしますが
今回はコスト面を重視し、初期投資と運用コストが低く抑えられるように
努力してみようと思います。
私はこういう物を買おうとするとどーしても、どうせ買うならハイスペック。
そんな嗜好があるので・・・
いやDellで買えばもっと安くあがったかもしれない・・・。まあいいや。
作者:art55
更新日:2008年11月29日 2時41分
【Tools】Visual Studio 2008 Service Pack 1(SP1)用Intellisenseの修正プログラム
Visual Studio 2008 Service Pack 1(SP1)用Intellisenseの修正プログラムが公開されました
http://blogs.msdn.com/dd_jpn/archive/2008/11/26/9143673.aspx
Visual Studio 2008 Service Pack 1(SP1) 用 Intellisense の修正プログラムを本日公開いたしましたので、お知らせいたします。
お〜ってかアレはバグだったんですね・・・。そういうものだと思ってました。
作者:art55
更新日:2008年11月28日 20時10分
【.NET】Dynamic Language Runtime
Dynamic Language Runtime
http://www.codeplex.com/dlr/
The Dynamic Language Runtime enables language developers to more easily create dynamic languages for the .NET platform. In addition to being a pluggable back-end for dynamic language compilers, the DLR provides language interop for dynamic operations on objects. The DLR has common hosting APIs for using dynamic languages as libraries or for scripting in your .NET applications. This project provides one stop shopping for the DLR components, our open source implementations of IronPython and IronRuby, documentation, and samples.
要チェックや!
作者:art55
更新日:2008年11月28日 20時2分
【.NET】プロパティ間ロジックの実現 その1

Source and Project
先日、自作したBindingを考察したいと思います。
まず、PropertyChangedEventManagerを経由せずに直接に
Source → Targetをあつかった場合は
INotifyPropertyChangedのPropertyChangedEventHandlerを
Targetが直接ハンドルするということになります。
一番、シンプルな形です。

IWeakEventListenerの価値をあまり理解していないのでこういうことを書くのは
大変、勇気がいることですが、つまりSourceのハンドラをTarget(リスナー)がハンドルすると
SourceがTargetへの参照を保持して、適切なタイミングで
ガベージュコレクトすることができないってことらしいです。
ええ。MSDNの受け売りです。
Bindingなど、SourceとTarget(リスナー)が互いに独立していたい場合は
なるべく弱い参照であることが望まれるということでしょうか・・・書いていて不安です(笑)
という訳で、WeakEventManagerで登録されたイベントをとりあえず受け付けて
適切なリスナーに変更を通知してくれるように、
前回作成したBindingはWeakEventManagerを使用しているわけです。
さて、そのトンチ絵が下記のとおりです。

TargetとListenerは分離して、SourceとListenerは、互いに独立しています。
WeakEventManagerのなかの実装を見ないとはっきりとわかりませんが、
弱い参照以上の参照レベルが実現できていると思われます。
しかし、ListenerとTargetが前回の実装ではListenerがTargetを参照しており(たぶん)
これってまずいような気がするなぁ〜って思ったので、
ちょこっと実装をいじって弱い参照をイベントハンドラ内で使用するようにしてみました。
つまりSourceからListenerへ変更通知が伝わり
さらにListenerのリスナーであるTargetへ変更通知は
Targetがガベージュコレクトされていない限りは通知する。
さらにTargetはListenerと独立してガベージュコレクトの対象となる。
という実装にしてみました(したつもりです)
では、コードを
弱い参照を一時的に強い参照へ昇格させるオブジェクトを実装してみました。
AliveObject.cs
--------------------------------------------------
internal class AliveObject : IDisposable
{
public AliveObject(WeakReference reference)
{
// NOTE: 下記の順序を入れ替えてはいけない。
Data = reference.Target;
IsActive = reference.IsAlive;
}
public object Data { get; private set; }
public bool IsActive { get; private set; }
public void Dispose()
{
Data = null;
}
}
PropertyBindingOperation.cs
-----------------------------------------------------
public static class PropertyBindingOperation
{
public static void SetBinding(object target, string path, PropertyBinding binding)
{
if (target == null || string.IsNullOrEmpty(path) || binding == null)
throw new ArgumentException();
SetUpdateTarget(path, binding, new WeakReference(target));
}
private static void SetUpdateTarget(string path, PropertyBinding binding, WeakReference targetWeakReference)
{
binding.UpdateTarget += delegate(object sender, PropertyChangedEventArgs e)
{
var source = sender as INotifyPropertyChanged;
if (source == null)
return;
object value;
if (!source.TryGetValue(e.PropertyName, out value))
return;
// ToDo: Converterなどをここで行う。
SetValueToTarget.Execute(targetWeakReference, path, value);
};
}
private static bool TryGetValue(this INotifyPropertyChanged source, string propertyName, out object value)
{
value = null;
Type type = source.GetType();
PropertyInfo propertyInfo = type.GetProperty(propertyName);
if (propertyInfo == null)
return false;
value = propertyInfo.GetValue(source, null);
return true;
}
}
static class SetValueToTarget
{
public static void Execute(WeakReference targetWeakReference, string path, object value)
{
using (AliveObject targetObject = targetWeakReference.GetTargetObject())
{
if (targetObject.IsActive)
targetObject.Data.SetValue(path, value);
}
}
private static AliveObject GetTargetObject(this WeakReference weakReference)
{
return new AliveObject(weakReference);
}
private static void SetValue(this object target, string path, object value)
{
Type targetType = target.GetType();
MethodInfo methodInfo = targetType.GetProperty(path).GetSetMethod();
if (methodInfo == null)
throw new ArgumentException();
methodInfo.Invoke(target, new[] { value });
}
}
データと取り出す部分、データを挿入する部分、あとその間でコンバートと
Binding内での操作のタイミングやバリエーションがいろいろあるので
このあたりをいろいろやっちゃうのは楽しそうです。
PropertyBinding.cs
----------------------------------------------------
public class PropertyBinding : IWeakEventListener
{
public PropertyBinding(INotifyPropertyChanged source, string path)
{
if (source == null)
throw new ArgumentNullException();
sourceRef = new WeakReference(source);
Path = path;
PropertyChangedEventManager.AddListener(source, this, path ?? string.Empty);
}
private readonly WeakReference sourceRef;
public INotifyPropertyChanged Source
{
get { return sourceRef.Target as INotifyPropertyChanged; }
}
public string Path { get; private set; }
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (CanUpdateTarget(managerType, e))
UpdateTarget(sender, (PropertyChangedEventArgs) e);
else
return false;
return true;
}
private bool CanUpdateTarget(Type managerType, EventArgs e)
{
return managerType == typeof(PropertyChangedEventManager) &&
e is PropertyChangedEventArgs &&
UpdateTarget != null;
}
public event PropertyChangedEventHandler UpdateTarget;
}
Sourceも参照を出すようにしてみました。
さてさて、これからなんですが、
Bindingはそのままにして、SourceとTargetのオブジェクトを変更し遊んでみようかなって思ってます。
普通、演算を行う場合、オブジェクトとオブジェクトの間に演算子を配置しますが、
演算子を固定し、オブジェクトを好きな場所に置くというプログラミングっていうのが
実現できるのかなってわけのわからないことを、想像しています。

で、最後の妄想です。

最初っから最後までもうそうでした。ごめんなさい。
Source and Project
作者:art55
更新日:2008年11月28日 2時45分
【.NET】弱いつながりでWeakReference

Source and Project
昨日、IWeakEventListenerを紹介させていただきました。
それで今日は「弱い」つながりでWeakReferenceを動きをちょっとだけみてみました。
WeakReferenceはMSDNの噂によると...
WeakReference クラス
"弱い参照" を表します。弱い参照は、オブジェクトがガベージ コレクションによるクリアの対象になっている状態のままで、そのオブジェクトを参照します。
http://msdn.microsoft.com/ja-jp/library/system.weakreference.aspx
MSDNのサンプルコードはなかなか奇妙奇天烈で、わかりにくいです。
ということで、今回はシンプルなサンプルコード書いてみて動きを見てみました。
これはむしろGC.Collect()の動きを確かめているだけのような気がしなくでもないわけですが・・・
class Program
{
static void Main(string[] args)
{
var weakReferenceList = new List<WeakReference>();
var referenceList = new List<Data>();
for (int i = 0; i < 12; i++)
{
var data = new Data();
if (i % 2 == 0)
referenceList.Add(data);
weakReferenceList.Add(new WeakReference(data, false));
data = null;
}
GC.Collect();
foreach (WeakReference weakReference in weakReferenceList)
{
var data = (Data) weakReference.Target;
if (data != null)
Console.WriteLine(weakReferenceList.IndexOf(weakReference) + " is Alive.");
else
Console.WriteLine(weakReferenceList.IndexOf(weakReference) + " is not Alive.");
}
}
}
class Data
{
public Data()
{
Item = new byte[1024];
}
public int Index { get; set; }
public object Item { get; set; }
}
ちなみに
for (int i = 0; i < 12; i++)
{
...
data = null;
}
のdata = nullを入れていなくて、必ず最後の項目がガベージュコレクトされず
List
実行結果は下記のとおり
------------------------------
0 is Alive.
1 is not Alive.
2 is Alive.
3 is not Alive.
4 is Alive.
5 is not Alive.
6 is Alive.
7 is not Alive.
8 is Alive.
9 is not Alive.
10 is Alive.
11 is not Alive.
WeakReferenceは誰からも参照されていないものを集める場合に便利そうです。
いや、むしろ参照されているものを集めるのに便利そうと言うべきか・・・。
絵で描いたらわかりやすいなぁ〜って思って書いてみました。
TargetとなるオブジェクトをA, B, WeakReferenceのオブジェクトが
それぞれ参照していたとします。
このときは当然、AとBが参照しているのでTargetオブジェクトはGCの対象とはなりません。

しかし、AとBの参照が何らかの理由でなくなり、WeakReferenceだけが
Targetオブジェクトを参照していた場合、TargetオブジェクトはGCの対象となります。

さらにガベージュコレクト走るとTargetオブジェクトはゴミ箱へ行ってしまい、
WeakReferenceの参照先はnullになってしまいます。
そのためWeakReferenceのオブジェクトがたとえばwという名前だった場合
w.Targetはnullを返すわけです。

ちなみに絵を使って説明したかったわけではなく
単にゴミ箱が書きたかったというのは内緒にしておいてください。
Source and Project
作者:art55
更新日:2008年11月27日 2時48分