私がこれを求めている理由は、@ Greg D( この質問 から)によって代わりにSetCurrentValue()
を使用するように勧められたためですが、ドキュメントを見てみましたが、表示されませんでした違いは何ですか。または、「バリューソースを変更せずに」とはどういう意味ですか?
依存関係プロパティ識別子で指定された、依存関係プロパティのローカル値を設定します。
値のソースを変更せずに、依存関係プロパティの値を設定します。
あなたが提供したMSDNリンクはそれを非常によく言っています:
このメソッドは、アプリケーションが宣言したプロパティの使用を無効にすることなく、独自のプロパティの1つの値をプログラムで設定するコンポーネントによって使用されます。 SetCurrentValueメソッドはプロパティの有効な値を変更しますが、既存のトリガー、データバインディング、およびスタイルは引き続き機能します。
TextBox
コントロールを作成していて、人々が次のようによく使用するText
プロパティを公開したとします。
<TextBox Text="{Binding SomeProperty}"/>
コントロールのコードで、SetValue
を呼び出すと、上書き指定したものとのバインディングになります。ただし、SetCurrentValue
を呼び出すと、プロパティが指定された値をとることが保証されますが、バインディングは破棄されません。
私の知る限り、グレッグのアドバイスは正しくありません。 CLRラッパープロパティからは常にGetValue
/SetValue
を使用する必要があります。 SetCurrentValue
は、特定の値を取得するためにプロパティが必要であるが、プロパティに対して構成されているバインディング、トリガー、またはスタイルを上書きしたくないシナリオでより役立ちます。
受け入れられた答えに加えて:
この投稿 がSetCurrentValue()を非常によく説明していることがわかりました。 Dependency Property Value Precedenceシステムが、バインドされた値を超えてローカル値を取得する方法に注意してください。これは、コメント投稿者の予期しない動作を説明しています。
デモハーネス(完全):
_class test : DependencyObject
{
static DependencyProperty XyzProperty =
DependencyProperty.Register("Xyz", typeof(int), typeof(test), new PropertyMetadata(42));
public test()
{
/* ... see code shown below ... */
}
void inf()
{
var info = DependencyPropertyHelper.GetValueSource(this, XyzProperty);
var msg = $@"{"//"
} {(int)GetValue(XyzProperty),2
} {(ReadLocalValue(XyzProperty) is int x ? "(Object)" + x : "UnsetValue"),12
} {info.BaseValueSource,9
} {(info.IsCurrent ? "" : "Not") + "Current",12
} {(info.IsCoerced ? "" : "Not") + "Coerced",12
}";
Trace.WriteLine(msg);
}
};
_
ディスカッションの例:
_ // v̲a̲l̲u̲e̲ s̲t̲o̲r̲e̲d̲-o̲b̲j̲ B̲V̲S̲ C̲u̲r̲r̲e̲n̲t̲? C̲o̲e̲r̲c̲e̲d̲?
/*1*/ // 42 UnsetValue Default NotCurrent NotCoerced
/*2*/ SetValue(XyzProperty, 5); // 5 (Object)5 Local NotCurrent NotCoerced
/*3*/ SetValue(XyzProperty, 42); // 42 (Object)42 Local NotCurrent NotCoerced
/*4*/ ClearValue(XyzProperty); // 42 UnsetValue Default NotCurrent NotCoerced
/*5*/ SetCurrentValue(XyzProperty, 5); // 5 (Object)5 Default Current Coerced
/*6*/ SetCurrentValue(XyzProperty, 42); // 42 UnsetValue Default NotCurrent NotCoerced
/*7*/ SetValue(XyzProperty, 5); // 5 (Object)5 Local NotCurrent NotCoerced
SetCurrentValue(XyzProperty, 42); // 42 (Object)42 Local Current Coerced
_
ディスカッション:
DependencyProperty
が「42」である不在のDefaultValue
の初期状態では、_BaseValueSource.Default
_フラグがアサートされています。 ReadLocalValue()
は、グローバルシングルトンインスタンス_DependencyProperty.UnsetValue
_を返します。
SetValue()
は、期待どおりに_BaseValueSource.Local
_値を内部的に格納します。
SetValue
を使用してDefaultValue
と等しい値を格納しても、_BaseValueSource.Default
_状態は復元されません(以下の#6と比較してください)。
代わりに、保存されている値またはバインディングの一部またはすべてを削除してDPを元の状態に復元する場合は、ClearValue()
を呼び出します。 (下記の注を参照)
SetCurrentValue()
を使用すると、プロパティ値は強制によって生成され、_BaseValueSource.Local
_モードはアサートされません。以前のBaseValueSource
Defaultは、プロパティが not であるにもかかわらず、実際にはDefaultValue
。
重要:
これは、GetValueSource()
によって返されるBaseValueSource
が_BaseValueSource.Default
_と等しいことを確認することは not aであることを意味します。優勢なプロパティ値がDPメタデータのデフォルト値であるかどうかの信頼できるインジケータ。
一方、上記の#3とは異なり、SetCurrentValue
does DPメタデータのDefaultValue
との同等性をチェックして、値をプルーニングすると見なします。 「不要」としても冗長。この熱心なクリーンアップは、DPストレージの肥大化を緩和するように設計されている場合がありますが、完全に理解されていない場合にあいまいなバグにつながる可能性がある特殊なケースの「マスキング解除」動作により、DP状態の透過性も複雑になります。たとえば、#6は、DPをクリアしてClearValue()
..と区別できない元の状態に戻します。
...ただし、以前に保存されたBaseValueSource
がCurrent
であり、Local
ではない場合のみ; #5 /#6をペア#7と比較してください。ペア#7では、報告されたプロパティ値が同じであるにもかかわらず、内部状態フラグが大幅に異なります。
ClearValue()
:に関して
PropertyChangedCallback
が、プロパティの以前の値から最終的に変更されないSetValue()
操作に対して呼び出されないことは明らかです。 SetValue
は、進行中の変更が作業中のアクティブなプロパティの値に関連しているという暗黙の前提を持っているため、これは基本的なことです。直感的ではないのは、同じロジックがClearValue()
にも適用されることです。
たとえば、#4では、ClearValue
により、ローカル値_42
_が内部DPストレージから削除され、その他の内部状態の変更もすべて期待どおりに行われます。問題は、OnPropertyChanged
が呼び出されるかどうか(または呼び出されないか)現在のClearValue
呼び出し中には、前の値等しいメタデータのデフォルト値になりました。
「クリア」操作のセマンティクスは、以前の状態の要約破棄を意味するように見えるため(したがって、コンテキスト上任意であると見なされることが多い)、ClearValue()
は、その前の状態にのみ依存します。特に、「変更」通知を起動するかどうかなど、new状態も関係する(および混ざり合う)重要な動作の場合。