private static object ConvertPropertyPath(XamlTypeConverter converter, ITypeDescriptorContext context, CultureInfo culture, object value) { string typename; string propertyname; string index; PropertyNodeType node; string str = (string)value; // Fastpath - if there are no prefixed types then we have nothing to expand if (!str.Contains(":")) { return(new PropertyPath(str)); } var parser = new PropertyPathParser(str); var expanded = new StringBuilder(); while ((node = parser.Step(out typename, out propertyname, out index)) != PropertyNodeType.None) { switch (node) { case PropertyNodeType.AttachedProperty: if (expanded.Length > 0) { expanded.Append('.'); } if (typename.Contains(":")) { typename = converter.parser.ResolveType(typename).ToString(); expanded.AppendFormat("('{0}'.{1})", typename, propertyname); } else { expanded.AppendFormat("({0}.{1})", typename, propertyname); } break; case PropertyNodeType.Indexed: expanded.AppendFormat("[{0}]", index); break; case PropertyNodeType.Property: if (expanded.Length > 0) { expanded.Append('.'); } expanded.Append(propertyname); break; default: throw new Exception(string.Format("Could not handle PropertyNodeType.{0}", node)); } } return(new PropertyPath(str, expanded.ToString())); }
internal PropertyPathWalker(string path, bool isDatacontextBound) { Path = path; StandardPropertyPathNode lastNode; IsDataContextBound = isDatacontextBound; if (path == null || path == ".") { //bindsDirectlyToSource set to true means that the binding is directly made to the source (--> there is no path) lastNode = new StandardPropertyPathNode(); //what to put in there ? FirstNode = lastNode; FinalNode = lastNode; } else { PropertyNodeType type; var parser = new PropertyPathParser(path); string typeName; string propertyName; int index; //IPropertyPathNode node; while ((type = parser.Step(out typeName, out propertyName, out index)) != PropertyNodeType.None) { //we make node advance (when it is not the first step, otherwise it stays at null) //node = FinalNode; //var isViewProperty = false; //boolean isViewProperty = CollectionViewProperties.Any (prop => prop.Name == propertyName); // static readonly PropertyInfo[] CollectionViewProperties = typeof (ICollectionView).GetProperties (); switch (type) { case PropertyNodeType.AttachedProperty: case PropertyNodeType.Property: if (FinalNode == null) { FinalNode = new StandardPropertyPathNode(typeName, propertyName); } else { FinalNode.Next = new StandardPropertyPathNode(typeName, propertyName); } break; case PropertyNodeType.Indexed: throw new NotImplementedException("Indexed properties are not supported yet."); //todo: when we will handle the indexed properties, uncomment the following //node.Next = new IndexedPropertyPathNode(index); break; default: break; } if (FirstNode == null) { FirstNode = FinalNode; } if (FinalNode.Next != null) { FinalNode = FinalNode.Next; } } } this.FinalNode.Listen(this); }
private IEnumerable <Tuple <DependencyObject, DependencyProperty, int?> > defaulAccessVisualStateProperty(DependencyObject rootTargetObjectInstance) { PropertyPathParser parser = new PropertyPathParser(Path); string typeName, propertyName, index; PropertyNodeType type; var nodes = new List <Tuple <PropertyNodeType, Tuple <string /*type*/, string /*property*/, string /*index*/> > >(); while ((type = parser.Step(out typeName, out propertyName, out index)) != PropertyNodeType.None) { nodes.Add( new Tuple <PropertyNodeType, Tuple <string, string, string> >( type, new Tuple <string, string, string>(typeName, propertyName, index))); } int count = Math.Max(0, nodes.Count - 1); List <Tuple <DependencyObject, DependencyProperty, int?> > list = new List <Tuple <DependencyObject, DependencyProperty, int?> >(count); for (int j = 0; j < count; ++j) { type = nodes[j].Item1; typeName = nodes[j].Item2.Item1; propertyName = nodes[j].Item2.Item2; index = nodes[j].Item2.Item3; Tuple <DependencyObject, DependencyProperty, int?> tuple; DependencyObject targetDO; switch (type) { case PropertyNodeType.AttachedProperty: case PropertyNodeType.Property: targetDO = list.Count == 0 ? rootTargetObjectInstance : list[list.Count - 1].Item1; Type targetType = targetDO.GetType(); PropertyInfo prop = targetType.GetProperty(propertyName); DependencyObject value = (DependencyObject)prop.GetValue(targetDO); DependencyProperty dp = (DependencyProperty)prop.DeclaringType.GetField(propertyName + "Property").GetValue(null); tuple = new Tuple <DependencyObject, DependencyProperty, int?>( value, dp, null); list.Add(tuple); yield return(tuple); break; case PropertyNodeType.Indexed: int i; int.TryParse(index, out i); targetDO = rootTargetObjectInstance; if (list.Count > 0) { #if OPENSILVER if (true) #elif BRIDGE if (CSHTML5.Interop.IsRunningInTheSimulator) #endif { // Note: In OpenSilver, we want to enter this case both in the simulator and // the browser. targetDO = (DependencyObject)((dynamic)list[list.Count - 1].Item1)[i]; } else { // Note: getItem() is the indexer's name in the Bridge implementation. // The use of 'dynamic' makes the above line return undefined when the application // is running in javascript with CSHTML5. targetDO = (DependencyObject)((dynamic)list[list.Count - 1].Item1).getItem(i); } } tuple = new Tuple <DependencyObject, DependencyProperty, int?>( targetDO, null, i); list.Add(tuple); yield return(tuple); break; } } if (!INTERNAL_IsDirectlyDependencyPropertyPath) { bool success = false; DependencyProperty dp = null; try { string name = nodes[nodes.Count - 1].Item2.Item2; DependencyObject finalDO = count == 0 ? rootTargetObjectInstance : list[list.Count - 1].Item1; dp = (DependencyProperty)finalDO.GetType() .GetField(name + "Property", BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public) .GetValue(null); success = dp != null; } finally { if (success) { INTERNAL_IsDirectlyDependencyPropertyPath = true; INTERNAL_DependencyProperty = dp; INTERNAL_DependencyPropertyName = dp.Name; } } } }
public PropertyPathWalker(string path, bool bindDirectlyToSource, bool bindsToView, bool isDataContextBound) { IsDataContextBound = isDataContextBound; string index; string propertyName; string typeName; PropertyNodeType type; CollectionViewNode lastCVNode = null; Path = path; if (string.IsNullOrEmpty(path) || path == ".") { // If the property path is null or empty, we still need to add a CollectionViewNode // to handle the case where we bind diretly to a CollectionViewSource. i.e. new Binding () { Source = cvs } // An empty path means we always bind directly to the view. Node = new CollectionViewNode(bindDirectlyToSource, bindsToView); lastCVNode = (CollectionViewNode)Node; FinalNode = Node; } else { var parser = new PropertyPathParser(path); while ((type = parser.Step(out typeName, out propertyName, out index)) != PropertyNodeType.None) { bool isViewProperty = CollectionViewProperties.Any(prop => prop.Name == propertyName); IPropertyPathNode node = new CollectionViewNode(bindDirectlyToSource, isViewProperty); lastCVNode = (CollectionViewNode)node; switch (type) { case PropertyNodeType.AttachedProperty: case PropertyNodeType.Property: node.Next = new StandardPropertyPathNode(typeName, propertyName); break; case PropertyNodeType.Indexed: node.Next = new IndexedPropertyPathNode(index); break; default: throw new Exception("Unsupported node type"); } if (FinalNode != null) { FinalNode.Next = node; } else { Node = node; } FinalNode = node.Next; } } lastCVNode.BindToView |= bindsToView; FinalNode.IsBrokenChanged += delegate(object o, EventArgs e) { Value = ((PropertyPathNode)o).Value; var h = IsBrokenChanged; if (h != null) { h(this, EventArgs.Empty); } }; FinalNode.ValueChanged += delegate(object o, EventArgs e) { Value = ((PropertyPathNode)o).Value; var h = ValueChanged; if (h != null) { h(this, EventArgs.Empty); } }; }
public PropertyPathWalker (string path, bool bindDirectlyToSource, bool bindsToView, bool isDataContextBound) { IsDataContextBound = isDataContextBound; string index; string propertyName; string typeName; PropertyNodeType type; CollectionViewNode lastCVNode = null; Path = path; if (string.IsNullOrEmpty (path) || path == ".") { // If the property path is null or empty, we still need to add a CollectionViewNode // to handle the case where we bind diretly to a CollectionViewSource. i.e. new Binding () { Source = cvs } // An empty path means we always bind directly to the view. Node = new CollectionViewNode (bindDirectlyToSource, bindsToView); lastCVNode = (CollectionViewNode) Node; FinalNode = Node; } else { var parser = new PropertyPathParser (path); while ((type = parser.Step (out typeName, out propertyName, out index)) != PropertyNodeType.None) { bool isViewProperty = CollectionViewProperties.Any (prop => prop.Name == propertyName); IPropertyPathNode node = new CollectionViewNode (bindDirectlyToSource, isViewProperty); lastCVNode = (CollectionViewNode) node; switch (type) { case PropertyNodeType.AttachedProperty: case PropertyNodeType.Property: node.Next = new StandardPropertyPathNode (typeName, propertyName); break; case PropertyNodeType.Indexed: node.Next = new IndexedPropertyPathNode (index); break; default: throw new Exception ("Unsupported node type"); } if (FinalNode != null) FinalNode.Next = node; else Node = node; FinalNode = node.Next; } } lastCVNode.BindToView |= bindsToView; FinalNode.IsBrokenChanged += delegate (object o, EventArgs e) { Value = ((PropertyPathNode) o).Value; var h = IsBrokenChanged; if (h != null) h (this, EventArgs.Empty); }; FinalNode.ValueChanged += delegate (object o, EventArgs e) { Value = ((PropertyPathNode) o).Value; var h = ValueChanged; if (h != null) h (this, EventArgs.Empty); }; }