/// <summary> /// Given the instance <paramref name="obj"/> and the <paramref name="memberName"/>, /// this method searches the best matching member on the instance. It first searches /// a property with name [PropertyName]Property, casts it to /// <see cref="AbstractProperty"/> and returns a <see cref="DependencyPropertyDataDescriptor"/> /// for it in the parameter <paramref name="dd"/>. If there is no such property, this method /// searches a simple property with the given name, returning a property descriptor for it. /// Then, the method will search for a field with the specified name, returning a /// <see cref="FieldDataDescriptor"/> for it. /// If there is no member found with the given name, this method returns false and a /// <c>null</c> value in <paramref name="dd"/>. /// </summary> /// <param name="obj">The object where to search the member with the /// specified <paramref name="memberName"/>.</param> /// <param name="memberName">The name of the member to be searched.</param> /// <param name="dd">Data descriptor which will be returned for the property or member, /// if it was found, else a <c>null</c> value will be returned.</param> /// <returns><c>true</c>, if a member with the specified name was found, else <c>false</c>.</returns> public static bool FindMemberDescriptor(object obj, string memberName, out IDataDescriptor dd) { if (obj == null) { throw new NullReferenceException("Property target object 'null' is not supported"); } DependencyPropertyDataDescriptor dpdd; if (DependencyPropertyDataDescriptor.CreateDependencyPropertyDataDescriptor( obj, memberName, out dpdd)) { dd = dpdd; return(true); } SimplePropertyDataDescriptor spdd; if (SimplePropertyDataDescriptor.CreateSimplePropertyDataDescriptor( obj, memberName, out spdd)) { dd = spdd; return(true); } FieldDataDescriptor fdd; if (FieldDataDescriptor.CreateFieldDataDescriptor(obj, memberName, out fdd)) { dd = fdd; return(true); } dd = null; return(false); }
public static bool CreateDependencyPropertyDataDescriptor(object targetObj, string propertyName, out DependencyPropertyDataDescriptor result) { result = null; if (targetObj == null) { throw new NullReferenceException("Target object 'null' is not supported"); } AbstractProperty prop; if (!FindDependencyProperty(targetObj, ref propertyName, out prop)) { return(false); } result = new DependencyPropertyDataDescriptor(targetObj, propertyName, prop); return(true); }
/// <summary> /// Returns the information if the specified <paramref name="other"/> descriptor /// is targeted at the same property on the same object. /// </summary> /// <param name="other">Other descriptor whose target object and property should be compared.</param> public bool TargetEquals(DependencyPropertyDataDescriptor other) { return(_obj.Equals(other._obj) && _propertyName.Equals(other._propertyName)); }
public bool Evaluate(IDataDescriptor source, out IDataDescriptor result) { result = null; Type type; object obj; MemberInfo mi; if (!ExtractWorkingData(source, _memberName + "Property", out type, out obj, out mi)) { if (!ExtractWorkingData(source, _memberName, out type, out obj, out mi)) { return(false); } } if (mi is FieldInfo) { // Field access result = new FieldDataDescriptor(obj, (FieldInfo)mi); return(true); } if (mi is PropertyInfo) { // Property access PropertyInfo pi = (PropertyInfo)mi; // Handle indexed property object[] convertedIndices = null; // Check property indexer bool indicesOnProperty = _indices != null && _indices.Length > 0 && ReflectionHelper.ConsumeParameters(_indices, pi.GetIndexParameters(), false, out convertedIndices); if (!indicesOnProperty) { convertedIndices = null; } if (pi.PropertyType == typeof(AbstractProperty)) { // Property value -> request value and return DependencyPropertyDataDescriptor object val = pi.GetValue(obj, convertedIndices); if (val == null) { return(false); } result = new DependencyPropertyDataDescriptor(obj, _memberName, (AbstractProperty)val); } else { // Simple property result = new SimplePropertyDataDescriptor(obj, pi); if (convertedIndices != null && convertedIndices.Length > 0) { ((SimplePropertyDataDescriptor)result).Indices = convertedIndices; } } if (_indices != null && _indices.Length > 0 && !indicesOnProperty) { // Item or collection index -> handle index expression per IndexerPathSegment return(new IndexerPathSegment(_indices).Evaluate(result, out result)); } return(true); } if (mi is MethodInfo) { // Method invocation is not supported in evaluation return(false); } // Unsupported member type return(false); }
/// <summary> /// Returns the information if the specified <paramref name="other"/> descriptor /// is targeted at the same property on the same object. /// </summary> /// <param name="other">Other descriptor whose target object and property should be compared.</param> public bool TargetEquals(DependencyPropertyDataDescriptor other) { return _obj.Equals(other._obj) && _propertyName.Equals(other._propertyName); }
public static bool CreateDependencyPropertyDataDescriptor(object targetObj, string propertyName, out DependencyPropertyDataDescriptor result) { result = null; if (targetObj == null) throw new NullReferenceException("Target object 'null' is not supported"); AbstractProperty prop; if (!FindDependencyProperty(targetObj, ref propertyName, out prop)) return false; result = new DependencyPropertyDataDescriptor(targetObj, propertyName, prop); return true; }
/// <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); } }