作为记录:我在这里发现了一个类似的问题,但我必须详细说明这个主题。
我的具体情况是这样的:
在 Silverlight 4 中,该myFrameworkElement.FindName("otherElementName")
方法现在似乎工作正常,但我遇到了一个问题。null
当元素显然还没有添加到可视化树时,它仍然会返回。
但是现在我需要在DependencyProperty
自PropertyChangedCallback
定义UserControl
处理程序中使用此功能。在此范围内,尚不确定 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 的最佳方法是什么?
已经感谢您的耐心和时间阅读我冗长的阐述。;-)