我发现了一个类似的问题
here
但我必须在这个问题上再详细阐述一点。
我的具体设想是:
在Silverlight 4中,
myFrameworkElement.FindName("otherElementName")
方法现在似乎工作正常,但我遇到了一个问题。它还会回来
null
当元素显然还没有添加到可视化树中时。
但现在我需要在
DependencyProperty
的
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
处理程序内部。然后我去取消订阅处理程序内部的事件,因为我是一个聪明和干净的人,不希望泄漏。我也不想在这里用一些精美的纺织厂或类似的东西来打破任何飞在轮子上的苍蝇。
到目前为止,这项工作进展顺利。但我有一些问题。
-
这通常是一种足够干净的方法来取消订阅处理程序内部的事件处理程序吗?还是最终会杀死一只无辜的小狗?
-
在匿名委托中使用外部作用域变量可能会出现一些问题,比如泄漏吗?
-
是否有线程同步问题会导致我“错过”
Loaded
事件?在这个特殊的场景中,只应涉及Silverlight的UI Dispatcher线程。但是,如果这仍然是一个问题,并且/或者如果我在一个非UI相关的场景中需要类似的功能,那么F1X0R IT的最佳方法是什么?
感谢您的耐心和时间阅读我冗长的阐述。;-)