あるクラスの某プロパティが欲しい時

あるクラス(X)の某プロパティ(P)が欲しい時、特に意識する事なくgetアクセサを使う。

var instanceOfX = new X();
var val = instanceOfX.P;
まあ、これはC#のコード上で取得したいプロパティがわかっているからできる事なんだけど。じゃあ、外部から与えられたプロパティ名(文字列)の値を取得したい時とかどうするだろう?
→これはリフレクションを使うことになる。メソッド化してみた。
using System;

namespace TawamureDays {

public static class Utils {

/// <summary>
/// 指定のオブジェクトから、指定されたプロパティ(文字列)の値を取得します。
/// </summary>
/// <param name="obj">オブジェクト</param>
/// <param name="propName">プロパティ名</param>
/// <returns>プロパティが持つ値</returns>
public static object GetProperty1(object obj, string propName) {
if (obj == null) {
throw new ArgumentNullException("obj");
}

if (string.IsNullOrWhiteSpace(propName)) {
throw new ArgumentNullException("propName");
}

var propInfo = obj.GetType().GetProperty(propName,
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance);

if (propInfo != null) {
return propInfo.GetValue(obj, null);
} else {
return null;
}
}
}
}
なお、このメソッドの場合、「プロパティは存在するが、値がnull」と「プロパティは存在しないので、null」との区別がつかない。付けたい場合は、以下のようにするのも1つの手。
using System;

namespace TawamureDays {

public static class Utils {

/// <summary>
/// 指定のオブジェクトから、指定されたプロパティ(文字列)の値を取得します。
/// </summary>
/// <param name="obj">オブジェクト</param>
/// <param name="propName">プロパティ名</param>
/// <returns>プロパティが持つ値</returns>
public static Tuple<bool, object> GetProperty1(object obj, string propName) {
if (obj == null) {
throw new ArgumentNullException("obj");
}

if (string.IsNullOrWhiteSpace(propName)) {
throw new ArgumentNullException("propName");
}

var propInfo = obj.GetType().GetProperty(propName,
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance);

if (propInfo != null) {
return Tuple.Create(true, propInfo.GetValue(obj, null));
} else {
return Tuple.Create(false, null as object);
}
}
}
}
取得した値をそのまま使えなくなるというデメリットは発生するけど、戻り値のItem1で、プロパティの存在をチェックできる。何を今更な内容をだしておいて、リフレクションを使いはするけど、リフレクション以外でプロパティを取得する方法をメモしておく。
方法としては、以前にも書いた、インスタンスを生成する時に使った式木を使う。式木は使いようによって(キャッシュすることで)、リフレクションよりも高い性能を見せてくれる。

続きを読む
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

Template内のコントロールを検索する。

もう何度か書いてしまっているけども、カスタムコントロールや標準のコントロールは何かしらのテンプレートが適用されている。標準では提供されていない細かい事をしようと思うと、このテンプレート内のコントロールを検索して、イベントにハンドラメソッドを登録したり、目的のプロパティとバインディングする必要が出てくる。
ただ、このテンプレートって、実行時にも切り替えが可能だったりするので、一回取ったら終わり、とするわけには行かない。なので、OnApplyTemplateという、テンプレート適用時のメソッドをオーバーライドして、その都度削除したり取得したりする必要がある。
/// <summary>
/// テンプレート適用時の処理です。
/// </summary>
public override void OnApplyTemplate() {
//旧のTemplateに対しての削除処理

base.OnApplyTemplate();

if (this.Template != null) {
//新テンプレートに対する追加処理
}

return;
}
で、テンプレート内のコントロールを探すにもまずここで実行してみると便利かなと。
探し方は、Templateが持つFindNameメソッドで探すだけ。

//固定部のGridパネル
var panel = this.Template.FindName("PART_XXXXXXXX", this) as Grid;

第1引数がコントロール名で、第2引数がTemplateの親(持ち主)となる。メソッドは簡単なんだけど、問題は、テンプレート内のコントロールのがどういう名前で定義されているか、だったりする。
例えば、DatePickerで、IMEをOFFにする。で扱ったDatePicker内にあるTextBoxは、「PART_TextBox」という名前を持っている。
テンプレート内コントロール名の探し方は、2つある。他にあれば追記していく。

①定義参照で探す。
件のDatePickerなんかは、DatePickerへカーソルを持って行って、「定義を参照」とすると、以下のように出てくる。
namespace System.Windows.Controls
{
// 概要:
// ユーザーが日付を選択できるコントロールを表します。
[TemplatePart(Name = "PART_Popup", Type = typeof(Popup))]
[TemplatePart(Name = "PART_Root", Type = typeof(Grid))]
[TemplatePart(Name = "PART_TextBox", Type = typeof(DatePickerTextBox))]
[TemplatePart(Name = "PART_Button", Type = typeof(Button))]
public class DatePicker : Control

TemplatePartという属性は、テンプレートに名前(Nameやx:Name)を持つコントロールを示している。
PART_TextBoxという名前のコントロールは、DatePickerTextBoxというクラスであることがわかる。他にもポップアップやボタンが有ることがわかる。

②ソースコードを探す。できればXAML。
①でわからなかったのがDataGrid。定義参照してみたけど、TemplatePartが定義されてない。TemplatePartって、必須設定ではないんだね…Orz。結局、こういう場合は、ソースコードやテンプレートが定義されたリソース(XAML)、WPF4の書籍を探すしかない。書籍はTemplateに関する章周辺に掲載されている可能性が高い。DataGridは、WPF Toolkitのソースコードを探して見つけた。

細かいカスタマイズにはそれなりの苦労があるが、Windows.Formsに比べたらはるかにマシなのが、WPFの利点の一つかなと思えた。実際サードパーティ製品を購入しなくても、ある程度の事(Windows.Formsではできなかった事)ができてるしな。パフォーマンスはWindows.Forms以上に気を使う必要があるけど。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

マルチヘッダDataGridメモ-参(コントロールテンプレート)

まずはマルチヘッダ用のコントロールが必要となる。
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.Windows.Threading;

namespace TawamureDays {

/// <summary>
/// DataGrid マルチカラムヘッダ用コントロール
/// </summary>
[ContentProperty("Content")]
public class DataGridMultiHeader : ContentControl {

#region コンストラクタ

/// <summary>
/// staticコンストラクタ
/// </summary>
static DataGridMultiHeader() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridMultiHeader),
new FrameworkPropertyMetadata(typeof(DataGridMultiHeader)));
}

#endregion
}
}

ContentPropertyは、ContentControlのお約束な属性クラス。
マルチヘッダDataGridメモ-弐(DataGridの構造を理解する)で挙げたプロパティと連携する為の依存関係プロパティを実装する。
        /// <summary>
/// セル用パネルの水平方向オフセット値を取得|設定します。
/// </summary>
private double CellsPanelHorizontalOffset {
get { return (double)GetValue(CellsPanelHorizontalOffsetProperty); }
set { SetValue(CellsPanelHorizontalOffsetProperty, value); }
}

/// <summary>セル用パネルの水平方向オフセット値</summary>
private static readonly DependencyProperty CellsPanelHorizontalOffsetProperty =
DependencyProperty.Register("CellsPanelHorizontalOffset", typeof(double),
typeof(DataGridMultiHeader), new UIPropertyMetadata(0D));

/// <summary>
/// 非固定列ViewPort(表示スペース)の水平方向オフセット値を取得|設定します。
/// </summary>
private double NonFrozenColumnsViewportHorizontalOffset {
get { return (double)GetValue(NonFrozenColumnsViewportHorizontalOffsetProperty); }
set { SetValue(NonFrozenColumnsViewportHorizontalOffsetProperty, value); }
}

/// <summary>非固定列ViewPort(表示スペース)の水平方向オフセット値</summary>
private static readonly DependencyProperty NonFrozenColumnsViewportHorizontalOffsetProperty =
DependencyProperty.Register("NonFrozenColumnsViewportHorizontalOffset", typeof(double),
typeof(DataGridMultiHeader), new UIPropertyMetadata(0D));

/// <summary>
/// 垂直方向のスクロールバーの可視状態を取得|設定します。
/// </summary>
private Visibility VerticalScrollBarVisibility {
get { return (Visibility)GetValue(VerticalScrollBarVisibilityProperty); }
set { SetValue(VerticalScrollBarVisibilityProperty, value); }
}

/// <summary>垂直方向のスクロールバーの可視状態</summary>
private static readonly DependencyProperty VerticalScrollBarVisibilityProperty =
DependencyProperty.Register("VerticalScrollBarVisibility", typeof(Visibility),
typeof(DataGridMultiHeader), new UIPropertyMetadata(Visibility.Visible));

/// <summary>
/// 垂直方向のスクロールバーの幅を取得|設定します。
/// </summary>
private double VerticalScrollBarWidth {
get { return (double)GetValue(VerticalScrollBarWidthProperty); }
set { SetValue(VerticalScrollBarWidthProperty, value); }
}

/// <summary>垂直方向のスクロールバーの幅</summary>
private static readonly DependencyProperty VerticalScrollBarWidthProperty =
DependencyProperty.Register("VerticalScrollBarWidth", typeof(double),
typeof(DataGridMultiHeader), new UIPropertyMetadata(0D));

次、テンプレートを作るにあたって、基本的な構造を考える。
DataGridが持つ列ヘッダは、専用のItemsControlに格納されている。更にこのItemsControlには、専用のパネルクラスが利用されている。しかも、DataGridというコントロールの内部で利用される事が前提となっている、いわゆるワンオフなクラス群だったりする。最初、これ(DataGrid内で使われているロジック)を再利用できないかと、ソースコードとにらめっこした。大体は理解できるんだけど、マルチヘッダに利用できるか?と考えたら、「無理っぽい」という結論になってしまった。なので、WPF multi-column super headerにあったように、Gridパネルを駆使してどうにかする方法を考えた次第。

コントロールテンプレート実装メモ:
①DataGridを覆う為のDockPanelを準備する。
②DataGridの上部に張り付く為のBorder(DockPanel.Dock=Top)を①のDockPanelに追加する。
③DataGridはContentに設定される前提なので、ContentPresenterを①のDockPanelに追加する。
なので最も外側だけで見ると、DockPanel{Border(Top), ContentPresenter}になる。
④Border内に、各々の領域を確保する為のGridを追加する。
⑤④で追加したGridに、以下のコントロールを追加する。
 Rectangle:CellsPanelHorizontalOffset分の広さを確保する為のプレースホルダ
      DataGridRowHeaderの上あたりに居座る。
 Grid:固定列分の領域を確保するためのプレースホルダ。固定列用のマルチヘッダを表示させる領域になる。
 ScrollViewer:可変列分の領域を確保する為のプレースホルダ。DataGridがスクロールされのと同じようにスクロールされる必要がある。
 Rectangle:垂直方向のスクロールバー分の領域を確保する為のプレースホルダ。スクロールバーがAutoだった時も考える。
※各プレースホルダの幅や表示状態は、領域確保の対象とする部分と連携される。
マルチヘッダの部分は、GridとScrollViewer内に収められる。
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

マルチヘッダDataGridメモ-弐(DataGridの構造を理解する)

「DataGridの構造を理解する」と言っても、コードを読んで全部理解する必要はない。マルチヘッダを表示するにあたって、まず必要なのが、表示領域の把握である為、把握に必要なプロパティの値をDataGridから取得する。

20121126_2

①DataGridの列が表示されはじめる際に左端からの相対位置。
 プロパティ名:CellsPanelHorizontalOffset

②固定列(FrozenColumnCount内の列)が表示に必要とする幅
 プロパティ名:NonFrozenColumnsViewportHorizontalOffset
 
③垂直にスクロールするためのスクロールバーが表示される
 ※これはDataGridのプロパティで提供されていない為、DataGridの内部にあるスクロールバーコントロールをテンプレートから取得し、現在の表示状態と幅を取得する。このコントロールを取得する為には、DataGrid用のControlTemplateで、どういう名前で定義されているかを把握する必要がある。
 ・探す元としてつかったものは、WPF Toolkit 。.NET3.5時代のものであっても、DataGridのControlTemplateが記述されたXAMLファイルを入手できる。Template内のコントロール名はほぼ変わっていないので、問題なし。

これらのプロパティをMultiHeader側でも用意し、Content内のDataGridの各プロパティとバインディングする。

つづく。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

マルチヘッダDataGridメモ-壱

作ってみましたとも(弐)。で作った、マルチヘッダ(カラム)DataGridメモ

必要なもの:
・ContentControlを継承したカスタムコントロール:1つ。
・カスタムコントロール用のControlTemplate:1つ。
・DataGrid:1つ。

手順:
1:DataGridの内部構造を理解する。
2:それをもとにControlTemplateを構築していく。必要があれば、プロパティも追加していく。
3:マルチヘッダとする部分のコードを実装する。

つづく。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

作ってみましたとも(弐)。

作ってみましたのその弐。複数列ヘッダ
参考にしたのはここ(そのままではない)。

20121118_1
DataGridを継承してみたわけではなく、ContentControlを継承して、DataGridをラップしてみた。その中でゴチャゴチャと処理している。

列入替えも可能にしてみた。
20121118_2

20121118_3

実装で苦労した点:
・DataGridColumnの列幅を取得するのがめんどかった。
・DataGridColumnの列幅に「*」があると、それはそれでめんどくさかった。
・列順序入替えに対応するのがやっぱり(ry。
なんか、めんどくさいばっかやな…。同僚のが移ったか?

課題:
・複数列ヘッダ側をドラグ&ドロップできない。
・文字の表示以外はできない(水平方向の位置や文字色なんかはまだ設定できない)。
・1段分しか増やせない(2段以上は現状のロジックでは不可能)。
・コード量的には1000行もないが、ロジックは少し複雑(説明がめんどくさい)。
あ。水平スクロールへの対応がまだだったOrz。実装は続く。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

作ってみましたとも(壱)。

標準のメッセージボックスって、「はい/いいえ」「OK/Cancel/Abort」とか、決まったものしか出せない。標準なので仕方ない事なのかもしれない。ただ、仕事では、それ以外の選択肢を出したい時もある。
そのために、一々画面を自作するのもめんどくさい大変なんです。
というわけで、↓のを参考にして、自分で作ってみました。
WPF MessageBox
で、作った結果が↓。
20121117

・タイトルバーの左上にあるアイコンを削除している。
・×ボタンを押しても画面は終了しない。
・ボタンを並べる領域は、Control Brushというシステムリソースの色を使っている。

その気になれば、?以外のアイコンも表示できるけど、?以外で複数の選択肢ってあまり使わないし。
右上の×ボタンを無効化したかったんだけど、無効化すると、Alt+F4での終了を防げなかったんだよなぁ…。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

先頭から取得する。途中から取得する。

文字列から一部を抜き取りメソッドのように、LINQにもそんな感じのメソッドがある。
using System;
using System.Collections.Generic;
using System.Linq;

namespace TawamureDays {

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

var list = new List<int>(10) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

//先頭の5個を取得します。
var top5 = list.Take(5).ToList();//{1, 2, 3, 4, 5}
//先頭の5個以外を取得します。
var fromTop5 = list.Skip(5).ToList();//{6, 7, 8, 9, 10}
return;
}
}
}

Takeが先頭から指定個数を取得するメソッド。Skipが途中から取るメソッド。
なお、指定個数が多すぎても、エラーにはならない。
using System;
using System.Collections.Generic;
using System.Linq;

namespace TawamureDays {

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

var list = new List<int>(10) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

//先頭の15個を取得します。
var top5 = list.Take(15).ToList();//要素数:10
//先頭の15個以外を取得します。
var fromTop5 = list.Skip(15).ToList();//要素数:0
}
}
}

最後蛇足。LINQの性質。
using System;
using System.Collections.Generic;
using System.Linq;

namespace TawamureDays {

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

var list = new List<int>(10) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

//先頭の5個を取得します。
var top5 = list.Take(5);

var top5List1 = top5.ToList();//{1,2,3,4,5}
list.Insert(0, 11);
//結果は変わる。
var top5List2 = top5.ToList();//{11,1,2,3,4}
return;
}
}
}
LINQは、実行した(Takeメソッドをコールした)段階では、確定していない。
確定するのは、foreachでのループや、ToList(),ToArray()等のメソッドが呼ばれた時。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0

[資料的情報]Zen-Coding

HTMLの省略記法として、「Zen-Coding」なるものがあるらしい。
最近、仕事でWEBアプリを開発していないので、jQueryすらあんまり触れていない。
まあ、参考資料的なリンクを貼っておこう。
知らない人は損してる?コーディングが3倍速くなるZen-Codingを導入してみた
Zen Coding in Visual Studio 2012
「Zen Coding」でググれば色々出てくる。これって、JavaScriptのライブラリっぽいんだけど、HTMLの生成をどこでやってるんだろ?クライアントだったら使う気しないな…。
続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WEB | コメント: 0 | トラックバック: 0

閉じないで、隠れるだけ

開発する画面で、やたらコントロールが多い時、画面の起動そのものに、結構なコスト(メモリと時間)がかかることがある。
そういう場合、画面を閉じるのではなく、非表示にするという方法がある。
ウィンドウを閉じないで非表示にするサンプル
Hide a window instead of closing it in WPF

・モードレス起動のみ可能(モーダルでやると多分固まる)。
・HideとShowで非表示と表示を切り替える。
・通常のCloseは必ずキャンセルする。

MVVMパターンの場合、WindowというViewに対して、ViewModelから「終了ではなく非表示にして」というメッセージと、「非表示から表示にして」というメッセージを送る事ができる必要がある。かな?
まあ、Command化して、OneWayToSourceでバインドするという手もあるけど。
この方法、Windows.Formsで開発したときに実際に使った事があるので、起動が早くなるのは知っているけど、多くの画面を隠しすぎても、メモリを多く占有するので、加減が難しいんだよな。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

再利用もほどほどにという事だろうか。

仕事場の同僚が、開発中の画面で↓のようなエラーが出て色々と調べていた。

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=AreRowDetailsFrozen; DataItem=null; target element is 'DataGridDetailsPresenter' (Name=''); target property is 'SelectiveScrollingOrientation' (type 'SelectiveScrollingOrientation')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=HeadersVisibility; DataItem=null; target element is 'DataGridRowHeader' (Name=''); target property is 'Visibility' (type 'Visibility')

StackoverFlowにまさに同じエラーで悩んでいる人がいた。
WPF DataBinding Error: I have no idea how I'm getting this error
発生する状況として、何らかの状態変化をトリガーに、DataGridの表示非表示を切り替えた時に発生するらしい。
上のサイトには解決策となる情報がなかった。なので、同僚も悶々としながら探っていたらしい。

なお、AreRowDetailsFrozenプロパティは、↓のようなもの。
AreRowDetailsFrozenプロパティ
DataGridには、RowDetailという「行の詳細を表示する」という機能があったりする。行に紐付く複数項目とか、その行に関連する画像を表示してみたりする事が可能らしい。その部分を水平方向にスクロールできるかどうかの値ってところか。でも、特にRowDetailを設定しているわけでもないのに発生するんだよな。

なお、このエラー、仮想化モードを「Recycling」から「Standard」にすると発生しなくなった
「Recycling」モードは、DataGridRowだか、その子にあたるDataGridCellsPresenterクラスのインスタンスを使いまわそうとする。使い回さない「Standard」モードと違ってメモリの節約になって、良さげに思えるんだけど、どうも、リサイクルする際に、前に使っていた時の情報を中途半端に持っているらしく、上のようなエラーが出てみたり、何もしていないのにレイアウトが崩れてみたりと、自分的に良い思い出がない。
当面は「Standard」でいくしかないと改めて思った。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

ComboBoxに大量データ

ComboBoxに数千件のリストを表示しようとした。別にしたかったわけではなく、たまたまそうなった。
で、ドロップダウンボタン(▼)を押すと、とってももっさりした動きになった。押してから、リストを表示するまでに、2秒ほどの「溜め」を感じるほどに。これはあれだ。そうあれ。UI仮想化ができていない。すべてのアイテムについてコントロールを実体を作ってるんだと思い当たった。
というわけで、ComboBoxに大量データを表示する際の設定方法をメモっておく。

<ComboBox VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
VirtualizingStackPanelは、UI仮想化を行う為のパネル。これを使うことで、仮想化系の添付プロパティが活かされている。これを設定することで、とりあえず数千件レベルのリストもスムーズに展開できた。
まあ、コンボボックスに対して、数千件のアイテムを表示させて、ユーザがまともに目当てのものを検索できるのか?という懸念(問題)は解消できないていないけどね。続きを読む
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

ComboBox in ControlTemplate

仕事でControlTemplateを組む事があり、その中にComboBoxを組み込む必要があった。
で、ComboBoxのドロップダウンメニューを出したうえで画面を終了すると、裏でバインドエラーが出るようになった。

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'ComboBoxItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'ComboBoxItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment')

なんぞこれ?しかも質の悪いことに、コンボボックス内に表示したアイテム分発生している。100件のアイテムがあったら、上のエラー100個、合計200個のエラーが出ている事になる。このバインディングエラーというのが曲者で、パフォーマンスに悪影響を与えるものだ。調べてみたら、結構あった。
Resolving harmless binding errors in WPF
Combobox throwing Data Binding Error
ListBoxItem produces “System.Windows.Data Error: 4” binding error
最初のリンクにあった内容を引用すると

This is a "known" issue, and happens to all controls that contain dynamically created lists (all item controls i.e. ComboBox, menu, ListBox etc.). ControlTemplate of items in these controls (specifically MenuItem, ComboBoxItem etc.) try to find the nearest ItemsControl and bind to the VerticalAlignment and HorizonalAlignment properties and raises this error on not finding the source.

ComboBoxだけでなく、ListBox等、内容が動的に変わるコントロールに発生するらしい。解決策としては、Style設定をする事だそうだ。
<!-- ComboBox For Resolving Binding Error-->
<Style TargetType="ComboBoxItem">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
ま、解決策があるだけましか。.NET4.5でも試してみないとな。
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0

サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m