Event handling with an anonymous delegate
Asked Answered
S

1

0

For the record: I found a similar question here but I have to elaborate a bit more on on the subject.

My concrete scenario is this:

In Silverlight 4, The myFrameworkElement.FindName("otherElementName") method seems to work fine now, but I encountered a problem. It still returns null when the element is not yet added to the visual tree obviously.

But now I need this functionality in a DependencyProperty's PropertyChangedCallback of a custom UserControl handler. In this scope, it is uncertain if the UserControl is added to the visual tree yet. But I must execute a certain action on another element in the tree. When the element is already available, it can and should be done right now. If not, it must be done immediately when it is available. So I came up with this extension method that I can call like this:

myFrameworkElement.FindNameEnsured("otherElementName",
    result => this.DoSomethingWith(result));

The code for the extension method goes like this:

    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;
            }
        }

As you can see, I must use an anonymous delegate because I need the values for name and resultAction inside of the handler. I then go unsubscribe the event inside of the handler because I'm a smart and clean guy and want no leakage. I also don't want to break any flies on wheels here with some fancy WeakEventFactories or similar stuff.

Now this works smoothly so far. But I have some questions.

  1. Is this generally a clean enough approach to unsubscribe the event handler inside of the handler? Or is that going to kill an innocent puppy eventually?
  2. Could there be some issues like some leakage because of using outer scope variables inside the anonymous delegate?
  3. Can there be thread synchronization issues which would cause me to "miss" the Loaded event? In this special scenario, only the Silverlight's UI dispatcher thread should be involved. But if it's a problem anyway, and/or if I need a similar functionality in a non-UI related scenario, what's the best approach to f1x0r it?

Thanks already for your patience and time reading my lengthy elaborations. ;-)

Schweitzer answered 27/1, 2010 at 13:27 Comment(0)
M
2
  1. That should be fine, although it's a bit painful. LINQ to Rx has a nicer idea of unsubscription - when you subscribe, you're given an IDisposable which unsubscribes when you dispose it. That doesn't fit the existing event model though.
  2. I don't think you'll have any leakage in this particular case - there are some edge conditions where two different anonymous functions using variables in the same scope can each end up capturing variables they don't require, but it really is an edge case.
  3. You'd have to give more exact details about the hypothetical situation - what you were worried about exactly, how the event is implemented etc.
Mahican answered 27/1, 2010 at 13:33 Comment(1)
Alright, thanks for the answer Mr. Skeet. Regarding point (3), I will come back or post a new question once I found a scenario or it's become a serious issue pressing me. ;-)Schweitzer

© 2022 - 2024 — McMap. All rights reserved.