Для записи: я нашел аналогичный вопрос здесь, но мне нужно подробнее рассказать об этом.
Мой конкретный сценарий таков:
В 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. Но если это так или иначе, и/или если мне нужна аналогичная функциональность в сценарии, не относящемся к пользовательскому интерфейсу, какой лучший подход к f1x0r?
Спасибо за ваше терпение и время, читая мои длительные разработки.; -)