かなり奇妙に思える問題に遭遇しました。これがバグなのか、 WPFの設計機能なのかわかりません。
依存関係プロパティを持つ依存関係オブジェクトがあり、値の強制によって制約が適用され、他の依存関係プロパティとのバインディングでこのプロパティを使用すると、すべてが期待どおりに機能します。
しかし、POCO オブジェクトに対するバインディングでプロパティを使用しようとすると、問題が発生します。この場合、依存関係プロパティが変更されたときに POCO が更新されますが、値の強制が実行される前に、POCO に無効な値または同期されていない値が残ります。
次に例を示します。
public class TestDO : DependencyObject
{
public static DependencyProperty NumberProperty =
DependencyProperty.Register("Number", typeof(int), typeof(TestDO),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.None, OnNumberChanged, OnNumberCoerce));
public int Number
{
get { return (int)GetValue(NumberProperty); }
set { SetValue(NumberProperty, value); }
}
private static void OnNumberChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("DepObj: NumberChanged {0} --> {1}", e.OldValue, e.NewValue);
}
private static object OnNumberCoerce(DependencyObject d, object value)
{
int cval = (int)value;
if (cval > 10)
cval = 10;
else if (cval < -10)
cval = 10;
Console.WriteLine("DepObj: OnNumberCoerce: {0} --> {1}", value, cval);
return cval;
}
}
public class TestPOCO
{
private int _pocoNumber = 0;
public int PocoNumber
{
get { return _pocoNumber; }
set { _pocoNumber = value; }
}
}
これで、上記の型の 2 つのインスタンスと、Number プロパティのバインディングとテスト設定を作成できます。バインディングは POCO オブジェクトを更新しますが、値の強制の前に更新します。
// create a POCO object
var testPoco = new TestPOCO();
// create a dependency object
var testObj = new TestDO();
// create a binding between the NumberProperty of the Dependency Object and the
// PocoNumber of the POCO object
BindingOperations.SetBinding(testObj, TestDO.NumberProperty, new Binding("PocoNumber")
{
Source = testPoco,
Mode = BindingMode.TwoWay
});
// try setting a value of 100, to trigger value coercion
testObj.Number = 100;
Console.WriteLine("Poco Number = {0}", testPoco.PocoNumber); // displays 100
Console.WriteLine("DP Number = {0}", testObj.Number); // displays 10
2 つの DependencyObject 間にバインディングが存在する場合、これは当てはまりません。その場合、すべてが期待どおりに機能します。SetValue --> ValueCoercion --> PropertyChanged --> SetValue