使用匿名代理进行事件处理
为了记录:我在这里发现了一个类似的问题,但我必须详细阐述这个问题。
我的具体情况是这样的:
在Silverlight 4中, myFrameworkElement.FindName("otherElementName")
方法现在似乎正常工作,但我遇到了一个问题。 当元素尚未添加到可见树时,它仍然返回null
。
但是现在我需要在自定义UserControl
处理程序的DependencyProperty
的PropertyChangedCallback
中使用此功能。 在这个范围内,用户控件是否被添加到可视化树还不确定。 但是我必须对树中的另一个元素执行某种操作。 当元素已经可用时,它可以并且应该立即完成。 如果不是,它必须在可用时立即完成。 所以我想出了这样的扩展方法,我可以这样调用:
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;
}
}
正如你所看到的,我必须使用一个匿名委托,因为我需要resultAction
内的name
和resultAction
的值。 然后我退订处理程序内部的事件,因为我是一个聪明干净的人,不想泄漏。 我也不想用一些花哨的WeakEventFactories或类似的东西来打破轮子上的苍蝇。
现在这个工作顺利到目前为止。 但我有一些问题。
Loaded
事件? 在这种特殊情况下,只有Silverlight的UI调度程序线程应该参与其中。 但是,如果这是一个问题,并且/或者如果我在非UI相关场景中需要类似的功能,那么f1x0r的最佳方法是什么? 感谢您的耐心和时间阅读我冗长的阐述。 ;-)
IDisposable
,它会在你处置时取消订阅。 尽管如此,这并不适合现有的事件模型。