記録のために:ここで同様の質問を見つけましたが、この件についてもう少し詳しく説明する必要があります。
私の具体的なシナリオは次のとおりです。
Silverlight 4 では、このmyFrameworkElement.FindName("otherElementName")
方法は問題なく機能しているように見えますが、問題が発生しました。null
要素がまだビジュアルツリーに追加されていない場合でも、明らかに戻ります。
しかし今、カスタムハンドラDependencyProperty
のでこの機能が必要です。このスコープでは、UserControl がビジュアル ツリーにまだ追加されているかどうかは不明です。しかし、ツリー内の別の要素に対して特定のアクションを実行する必要があります。要素がすでに利用可能な場合は、すぐに実行できますし、実行する必要があります。そうでない場合は、利用可能になったらすぐに実行する必要があります。そこで、次のように呼び出すことができるこの拡張メソッドを思いつきました。PropertyChangedCallback
UserControl
myFrameworkElement.FindNameEnsured("otherElementName",
result => this.DoSomethingWith(result));
拡張メソッドのコードは次のようになります。
static public void FindNameEnsured(this FrameworkElement self,
string name, Action<object> resultAction)
{
if (self != null && resultAction != null)
{
object result = self.FindName(name);
if (result != null)
{
resultAction(result);
}
else
{
RoutedEventHandler handler = null;
handler = (sender, e) =>
{
result = self.FindName(name);
resultAction(result);
self.Loaded -= handler;
};
self.Loaded += handler;
}
}
ご覧のとおり、ハンドラーのname
およびresultAction
内部の値が必要なため、匿名デリゲートを使用する必要があります。次に、ハンドラー内のイベントのサブスクライブを解除します。これは、私が頭が良くてクリーンな男であり、漏れがないようにしたいからです。また、派手な WeakEventFactories や類似のものを使用して、車輪に乗ったハエを壊したくありません。
これで、これまでのところスムーズに動作します。しかし、いくつか質問があります。
- これは一般的に、ハンドラー内のイベントハンドラーのサブスクライブを解除するのに十分なクリーンなアプローチですか? それとも、罪のない子犬を最終的に殺すつもりですか?
- 匿名デリゲート内で外側のスコープ変数を使用するために、リークなどの問題が発生する可能性はありますか?
Loaded
イベントを「見逃す」原因となるスレッド同期の問題はありますか? この特別なシナリオでは、Silverlight の UI ディスパッチャー スレッドのみが関与する必要があります。しかし、とにかくそれが問題である場合、および/またはUIに関連しないシナリオで同様の機能が必要な場合、それをf1x0rするための最良のアプローチは何ですか?
私の長い説明を読んでくれてありがとう。;-)