protected IDataDescriptor GetDataDescriptor(UIElement element)
 {
     string targetName = Storyboard.GetTargetName(this);
       object targetObject = null;
       if (targetName == null)
     targetObject = element;
       else
       {
     INameScope ns = element.FindNameScope();
     if (ns != null)
       targetObject = ns.FindName(targetName);
     if (targetObject == null)
       targetObject = element.FindElement(new NameMatcher(targetName));
     if (targetObject == null)
       return null;
       }
       try
       {
     IDataDescriptor result = new ValueDataDescriptor(targetObject);
     if (_propertyExpression != null && _propertyExpression.Evaluate(result, out result))
       return result;
       }
       catch (XamlBindingException e)
       {
     ServiceRegistration.Get<ILogger>().Warn("PropertyAnimationTimeline: Error evaluating expression '{0}' on target object '{1}'", e, _propertyExpression, targetObject);
       }
       return null;
 }
        /// <summary>
        /// Does the lookup for our binding source data. This includes evaluation of our source
        /// properties and the lookup for the data context.
        /// </summary>
        /// <remarks>
        /// During the lookup, change handlers will be attached to all relevant properties
        /// on the search path to the binding source. If one of the properties changes,
        /// this binding will re-evaluate.
        /// </remarks>
        /// <param name="result">Resulting source descriptor, if it could be resolved.</param>
        /// <returns><c>true</c>, if the binding source could be found and evaluated,
        /// <c>false</c> if it could not be resolved (yet).</returns>
        protected bool GetSourceDataDescriptor(out IDataDescriptor result)
        {
            ResetChangeHandlerAttachments();
            result = null;
            try
            {
                switch (_typeOfSource)
                {
                case SourceType.DataContext:
                    return(FindDataContext(out result));

                case SourceType.SourceProperty:
#if DEBUG_BINDINGS
                    if (Source == null)
                    {
                        DebugOutput("GetSourceDataDescriptor doesn't have a Source", Source);
                    }
#endif
                    result = new DependencyPropertyDataDescriptor(this, "Source", _sourceProperty);
                    return(true);

                case SourceType.RelativeSource:
                    DependencyObject current = _contextObject;
                    if (current == null)
                    {
                        return(false);
                    }
                    switch (RelativeSource.Mode)
                    {
                    case RelativeSourceMode.Self:
                        result = new ValueDataDescriptor(current);
                        return(true);

                    case RelativeSourceMode.TemplatedParent:
                        while (current != null)
                        {
                            DependencyObject last = current;
                            FindParent(last, out current, FindParentMode.HybridPreferVisualTree);
                            UIElement lastUIElement = last as UIElement;
                            if (lastUIElement != null)
                            {
                                AttachToSourcePathProperty(lastUIElement.TemplateNameScopeProperty);
                                if (lastUIElement.IsTemplateControlRoot)
                                {
                                    result = new ValueDataDescriptor(current);
                                    return(true);
                                }
                            }
                        }
#if DEBUG_BINDINGS
                        DebugOutput("GetSourceDataDescriptor didn't find TemplateParent");
#endif
                        return(false);

                    case RelativeSourceMode.FindAncestor:
                        if (FindAncestor(current, out current, FindParentMode.HybridPreferVisualTree,
                                         RelativeSource.AncestorLevel, RelativeSource.AncestorType))
                        {
                            result = new ValueDataDescriptor(current);
                            return(true);
                        }
                        return(false);

                    //case RelativeSourceMode.PreviousData:
                    //  // TODO: implement this
                    //  throw new NotImplementedException(RelativeSourceMode.PreviousData.ToString());
                    default:
                        // Should never occur. If so, we have forgotten to handle a RelativeSourceMode
                        throw new NotImplementedException(
                                  string.Format("RelativeSourceMode '{0}' is not implemented", RelativeSource.Mode));
                    }

                case SourceType.ElementName:
                    INameScope nameScope;
                    if (!FindNameScope(out nameScope))
                    {
                        return(false);
                    }
                    object obj = nameScope.FindName(ElementName) as UIElement;
                    if (obj == null)
                    {
#if DEBUG_BINDINGS
                        DebugOutput("GetSourceDataDescriptor didn't find object with name '{0}'", ElementName);
#endif
                        return(false);
                    }
                    result = new ValueDataDescriptor(obj);
                    return(true);

                default:
                    // Should never occur. If so, we have forgotten to handle a SourceType
                    throw new NotImplementedException(
                              string.Format("SourceType '{0}' is not implemented", _typeOfSource));
                }
            }
            finally
            {
                AttachToSource(result);
                IObservable observable = result == null ? null : result.Value as IObservable;
                if (observable != null)
                {
                    AttachToSourceObservable(observable);
                }
            }
        }