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