WPF の Binding の状態を確認するには WPF の Binding デバッグ機構 を使います。
この機能は .NET Framework Version 3.5 で導入されました。
サポート対象は 3.0SP1 からになっています。
WPF の Binding の Converter が減る方向へ の場合はこのようにします。
<Window x:Class="TextBoxBindings.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextBoxBindings"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="Window1" Height="107" Width="300">
<Window.Resources>
<local:ToUpperConverter x:Key="ToUpperConverter"/>
</Window.Resources>
<Window.DataContext>
<local:Person />
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding Path=Name, Converter={StaticResource ToUpperConverter}, diag:PresentationTraceSources.TraceLevel=High}" />
<Button Content="Dummy" />
</StackPanel>
</Window>
以下の文が増えてますね。
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
diag:PresentationTraceSources.TraceLevel=High
さっそく Converter なしの確認をします。
System.Windows.Data Warning: 52 : Created BindingExpression (hash=35287174) for Binding (hash=45523402)
System.Windows.Data Warning: 54 : Path: 'Name'
System.Windows.Data Warning: 56 : BindingExpression (hash=35287174): Default mode resolved to TwoWay
System.Windows.Data Warning: 57 : BindingExpression (hash=35287174): Default update trigger resolved to LostFocus
System.Windows.Data Warning: 58 : BindingExpression (hash=35287174): Attach to System.Windows.Controls.TextBox.Text (hash=44419000)
System.Windows.Data Warning: 63 : BindingExpression (hash=35287174): Resolving source
System.Windows.Data Warning: 66 : BindingExpression (hash=35287174): Found data context element: TextBox (hash=44419000) (OK)
System.Windows.Data Warning: 74 : BindingExpression (hash=35287174): Activate with root item Person (hash=22597652)
System.Windows.Data Warning: 104 : BindingExpression (hash=35287174): At level 0 - for Person.Name found accessor RuntimePropertyInfo(Name)
System.Windows.Data Warning: 100 : BindingExpression (hash=35287174): Replace item at level 0 with Person (hash=22597652), using accessor RuntimePropertyInfo(Name)
System.Windows.Data Warning: 97 : BindingExpression (hash=35287174): GetValue at level 0 from Person (hash=22597652) using RuntimePropertyInfo(Name): <null>
System.Windows.Data Warning: 76 : BindingExpression (hash=35287174): TransferValue - got raw value <null>
System.Windows.Data Warning: 85 : BindingExpression (hash=35287174): TransferValue - using final value <null>
System.Windows.Data Warning: 91 : BindingExpression (hash=35287174): Got LostFocus event from TextBox (hash=44419000)
System.Windows.Data Warning: 86 : BindingExpression (hash=35287174): Update - got raw value 'aaa'
System.Windows.Data Warning: 90 : BindingExpression (hash=35287174): Update - using final value 'aaa'
System.Windows.Data Warning: 98 : BindingExpression (hash=35287174): SetValue at level 0 to Person (hash=22597652) using RuntimePropertyInfo(Name): 'aaa'
System.Windows.Data Warning: 91 : BindingExpression (hash=35287174): Got PropertyChanged event from Person (hash=22597652)
Got LostFocus event from TextBox に対して反応して SetValue at level 0 to Person (hash=22597652) using RuntimePropertyInfo(Name): 'aaa' があり、Person.Name に aaa が入ります。
しかし、Got PropertyChanged event from Person に対しては無反応です。
次に Converter ありの確認をします。
a を一個多めに入れています。
System.Windows.Data Warning: 52 : Created BindingExpression (hash=35287174) for Binding (hash=45523402)
System.Windows.Data Warning: 54 : Path: 'Name'
System.Windows.Data Warning: 56 : BindingExpression (hash=35287174): Default mode resolved to TwoWay
System.Windows.Data Warning: 57 : BindingExpression (hash=35287174): Default update trigger resolved to LostFocus
System.Windows.Data Warning: 58 : BindingExpression (hash=35287174): Attach to System.Windows.Controls.TextBox.Text (hash=44419000)
System.Windows.Data Warning: 63 : BindingExpression (hash=35287174): Resolving source
System.Windows.Data Warning: 66 : BindingExpression (hash=35287174): Found data context element: TextBox (hash=44419000) (OK)
System.Windows.Data Warning: 74 : BindingExpression (hash=35287174): Activate with root item Person (hash=22597652)
System.Windows.Data Warning: 104 : BindingExpression (hash=35287174): At level 0 - for Person.Name found accessor RuntimePropertyInfo(Name)
System.Windows.Data Warning: 100 : BindingExpression (hash=35287174): Replace item at level 0 with Person (hash=22597652), using accessor RuntimePropertyInfo(Name)
System.Windows.Data Warning: 97 : BindingExpression (hash=35287174): GetValue at level 0 from Person (hash=22597652) using RuntimePropertyInfo(Name): <null>
System.Windows.Data Warning: 76 : BindingExpression (hash=35287174): TransferValue - got raw value <null>
System.Windows.Data Warning: 78 : BindingExpression (hash=35287174): TransferValue - user's converter produced {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 84 : BindingExpression (hash=35287174): TransferValue - using fallback/default value ''
System.Windows.Data Warning: 85 : BindingExpression (hash=35287174): TransferValue - using final value ''
System.Windows.Data Warning: 91 : BindingExpression (hash=35287174): Got LostFocus event from TextBox (hash=44419000)
System.Windows.Data Warning: 86 : BindingExpression (hash=35287174): Update - got raw value 'aaaa'
System.Windows.Data Warning: 88 : BindingExpression (hash=35287174): Update - user's converter produced 'aaaa'
System.Windows.Data Warning: 90 : BindingExpression (hash=35287174): Update - using final value 'aaaa'
System.Windows.Data Warning: 98 : BindingExpression (hash=35287174): SetValue at level 0 to Person (hash=22597652) using RuntimePropertyInfo(Name): 'aaaa'
System.Windows.Data Warning: 91 : BindingExpression (hash=35287174): Got PropertyChanged event from Person (hash=22597652)
System.Windows.Data Warning: 97 : BindingExpression (hash=35287174): GetValue at level 0 from Person (hash=22597652) using RuntimePropertyInfo(Name): 'AAAA'
System.Windows.Data Warning: 76 : BindingExpression (hash=35287174): TransferValue - got raw value 'AAAA'
System.Windows.Data Warning: 78 : BindingExpression (hash=35287174): TransferValue - user's converter produced 'AAAA'
System.Windows.Data Warning: 85 : BindingExpression (hash=35287174): TransferValue - using final value 'AAAA'
こんどは、Got PropertyChanged event from Person に反応がありました。
GetValue at level 0 from Person (hash=22597652) using RuntimePropertyInfo(Name): 'AAAA' で Person.Name から AAAA を取得して、TransferValue - user's converter で Converter を通して TransferValue - using final value 'AAAA' で TextBox の Text として AAAA を使います。
Kazuki さんの Blog を補足します。
http://blogs.wankuma.com/kazuki/archive/2009/05/28/173774.aspx
WPF の Binding は TextBox に入力があってフォーカスが離れると property の set を呼びますが、
その時の INotifyPropertyChanged でのイベントには反応しません。
Binding.Converter プロパティ などがセットされていて property の 値と、
表示が変わってくるかもしれない時には INotifyPropertyChanged でのイベントに反応します。
つまり、property の set と TextBox 表示が変わる場合は Converter をつけるのが本来の形なのです。
これによって通常の場合は無駄な INotifyPropertyChanged でのイベントを無視できて処理が削減できるから反応が良くなるというわけです。
以下に例を挙げます。これならVS2008でWPFアプリケーションでも動作します。
今回 Vs2010では いちいち IValueConverter を作らせるのは手間だろうということで Converter をつけなくてもできるように配慮したようです。
using System.ComponentModel;
namespace TextBoxBindings
{
public class Person : INotifyPropertyChanged
{
#region INotifyPropertyChanged メンバ
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
#endregion
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
// 名前は大文字なのです
if (!string.IsNullOrEmpty(_name))
{
_name = _name.ToUpper();
}
OnPropertyChanged("Name");
}
}
}
}
using System;
using System.Windows;
using System.Windows.Data;
namespace TextBoxBindings
{
class ToUpperConverter : IValueConverter
{
#region IValueConverter メンバ
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is string)
{
//この場合は必要ないが・・・
return ((string) value).ToUpper();
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
#endregion
}
}
<Window x:Class="TextBoxBindings.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TextBoxBindings"
Title="Window1" Height="107" Width="300">
<Window.Resources>
<local:ToUpperConverter x:Key="ToUpperConverter"/>
</Window.Resources>
<Window.DataContext>
<local:Person />
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding Path=Name, Converter={StaticResource ToUpperConverter}}" />
<Button Content="Dummy" />
</StackPanel>
</Window>