Beispiel #1
0
        private void Btn_test_att_Click(object sender, RoutedEventArgs e)
        {
            Human human = new Human();

            School.SetGrade(human, 6);
            int grad = School.GetGrade(human);

            Msg($"School的GlobalIndex:{School.GradeProperty.GlobalIndex}");
            Msg($"human的LocalValueEnumerator的HashCode:{human.GetLocalValueEnumerator().GetHashCode()}");
            Msg($"human附加School的Grad属性值:{grad}");
            Msg($"human附加School的依赖属性个数:{human.GetLocalValueEnumerator().Count}");

            //遍历依赖属性
            LocalValueEnumerator loc = human.GetLocalValueEnumerator();

            while (loc.MoveNext())
            {
                Msg($"property: {loc.Current.Property.ToString()}");
                Msg($"Value: {loc.Current.Value.ToString()}");
                Msg($"GetHashCode: {loc.Current.GetHashCode().ToString()}");
                Msg($"GetType: {loc.Current.Property.GetType().ToString()}");
            }
        }
Beispiel #2
0
        private void UpdateActiveElementBindings()
        {
            if (Keyboard.FocusedElement != null &&
                Keyboard.FocusedElement is DependencyObject)
            {
                DependencyObject     element = (DependencyObject)Keyboard.FocusedElement;
                LocalValueEnumerator localValueEnumerator = element.GetLocalValueEnumerator();

                while (localValueEnumerator.MoveNext())
                {
                    BindingExpressionBase bindingExpression = BindingOperations.GetBindingExpressionBase(element,
                                                                                                         localValueEnumerator
                                                                                                         .Current
                                                                                                         .Property);

                    if (bindingExpression != null)
                    {
                        bindingExpression.UpdateSource();
                        bindingExpression.UpdateTarget();
                    }
                }
            }
        }
Beispiel #3
0
        public static bool IsValid(DependencyObject parent)
        {
            // Validate all the bindings on the parent
            bool valid = true;
            LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();

            while (localValues.MoveNext())
            {
                LocalValueEntry entry = localValues.Current;
                if (BindingOperations.IsDataBound(parent, entry.Property))
                {
                    Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                    foreach (ValidationRule rule in binding.ValidationRules)
                    {
                        ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null);
                        if (!result.IsValid)
                        {
                            BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                            System.Windows.Controls.Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null));
                            valid = false;
                        }
                    }
                }
            }

            // Validate all the bindings on the children
            for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                if (!IsValid(child))
                {
                    valid = false;
                }
            }

            return(valid);
        }
Beispiel #4
0
        GetTypeDependencyPropertiesCacheItem(
            Object serializableObject
            )
        {
            if (serializableObject == null)
            {
                throw new ArgumentNullException("serializableObject");
            }

            Type type = serializableObject.GetType();

            TypeDependencyPropertiesCacheItem
                cachedItem = (TypeDependencyPropertiesCacheItem)_typesDependencyPropertiesCacheTable[type];

            if (cachedItem == null)
            {
                //
                // This means that the type was not seen before
                // We have to create a new entry to that type
                //
                DependencyObject objectAsDependencyObject = serializableObject as DependencyObject;

                if (objectAsDependencyObject != null)
                {
                    //
                    // First we have to figure out if this dependency
                    // object has any dependency properties that can be
                    // serializable and this has to happen before creating
                    // any cache
                    //
                    DependencyPropertyList list = new DependencyPropertyList(1);

                    for (LocalValueEnumerator localValues = objectAsDependencyObject.GetLocalValueEnumerator();
                         localValues.MoveNext();)
                    {
                        DependencyProperty dependencyProperty = localValues.Current.Property;

                        list.Add(dependencyProperty);
                    }

                    if (list.Count > 0)
                    {
                        int numOfSerializableDependencyProperties = 0;

                        TypeDependencyPropertyCache[] dependencyPropertiesCache = new TypeDependencyPropertyCache[list.Count];

                        for (int indexInDependencyPropertyList = 0;
                             indexInDependencyPropertyList < list.Count;
                             indexInDependencyPropertyList++)
                        {
                            DependencyProperty dependencyProperty = list.List[indexInDependencyPropertyList];

                            DesignerSerializationVisibility visibility      = DesignerSerializationVisibility.Visible;
                            Type                  serializerTypeForProperty = null;
                            TypeConverter         typeConverterForProperty  = null;
                            DefaultValueAttribute defaultValueAttr          = null;
                            DesignerSerializationOptionsAttribute
                                 designerSerializationFlagsAttr = null;
                            Type propertyType = dependencyProperty.PropertyType;

                            //
                            // Get the static setter member for the DependencyProperty
                            //
                            MemberInfo memberInfo = dependencyProperty.
                                                    OwnerType.
                                                    GetMethod("Get" + dependencyProperty.Name,
                                                              BindingFlags.Public | BindingFlags.NonPublic |
                                                              BindingFlags.Static | BindingFlags.FlattenHierarchy);

                            // Note: This is because the IService model does not abide
                            // by this pattern of declaring the DependencyProperty on
                            // the OwnerType. That is the only exception case.
                            if (memberInfo == null)
                            {
                                //
                                // Create a PropertyInfo
                                //

                                PropertyInfo propertyInfo = null;

                                PropertyInfo[] properties = dependencyProperty.OwnerType.GetProperties();

                                String name = dependencyProperty.Name;

                                for (int i = 0;
                                     i < properties.Length && propertyInfo == null;
                                     i++)
                                {
                                    if (properties[i].Name == name)
                                    {
                                        propertyInfo = properties[i];
                                    }
                                }

                                if (propertyInfo != null)
                                {
                                    Debug.Assert(propertyInfo.PropertyType == dependencyProperty.PropertyType,
                                                 "The property type of the CLR wrapper must match that of the DependencyProperty itself.");

                                    memberInfo = propertyInfo;

                                    //
                                    // We have to special case Print Tickets here.
                                    // Print Tickets are defined on as dependency properties on
                                    // fixed objects of types:
                                    // o FixedDocumentSequence
                                    // o FixedDocument
                                    // o FixedPage
                                    // and in order to eliminate the dependency between
                                    // PresentationFramework and System.printing assemblies,
                                    // those dependency properties are defined as of type "object"
                                    // and hence if we are here and we have a property of name
                                    // "PrintTicket" and owned by one of the above mentioned types
                                    // we try to get the serializer for the PrintTicket object
                                    //
                                    if (propertyInfo.Name == XpsNamedProperties.PrintTicketProperty &&
                                        ((dependencyProperty.OwnerType == typeof(System.Windows.Documents.FixedPage)) ||
                                         (dependencyProperty.OwnerType == typeof(System.Windows.Documents.FixedDocument)) ||
                                         (dependencyProperty.OwnerType == typeof(System.Windows.Documents.FixedDocumentSequence))))
                                    {
                                        propertyType = typeof(PrintTicket);
                                    }
                                }
                            }

                            if (memberInfo != null &&
                                TypeDependencyPropertyCache.
                                CanSerializeProperty(memberInfo,
                                                     this,
                                                     out visibility,
                                                     out serializerTypeForProperty,
                                                     out typeConverterForProperty,
                                                     out defaultValueAttr,
                                                     out designerSerializationFlagsAttr) == true)
                            {
                                TypeCacheItem typeCacheItem = GetTypeCacheItem(propertyType);
                                serializerTypeForProperty = serializerTypeForProperty == null ? typeCacheItem.SerializerType : serializerTypeForProperty;
                                typeConverterForProperty  = typeConverterForProperty == null ? typeCacheItem.TypeConverter : typeConverterForProperty;

                                TypeDependencyPropertyCache
                                    dependencyPropertyCache = new TypeDependencyPropertyCache(memberInfo,
                                                                                              dependencyProperty,
                                                                                              visibility,
                                                                                              serializerTypeForProperty,
                                                                                              typeConverterForProperty,
                                                                                              defaultValueAttr,
                                                                                              designerSerializationFlagsAttr);

                                dependencyPropertiesCache[numOfSerializableDependencyProperties++] = dependencyPropertyCache;
                            }
                        }

                        if (numOfSerializableDependencyProperties > 0)
                        {
                            TypeDependencyPropertyCache[] serializableDependencyPropertiesCache =
                                new TypeDependencyPropertyCache[numOfSerializableDependencyProperties];

                            for (int indexInSerializableProperties = 0;
                                 indexInSerializableProperties < numOfSerializableDependencyProperties;
                                 indexInSerializableProperties++)
                            {
                                serializableDependencyPropertiesCache[indexInSerializableProperties] =
                                    dependencyPropertiesCache[indexInSerializableProperties];
                            }

                            cachedItem = new TypeDependencyPropertiesCacheItem(type,
                                                                               serializableDependencyPropertiesCache);

                            _typesDependencyPropertiesCacheTable[type] = cachedItem;
                        }
                    }
                }
            }

            return(cachedItem);
        }
        /// <summary>
        ///     Returns a collection of properties for our object.  We first rely on base
        ///     CLR properties and then we attempt to match these with dependency properties.
        /// </summary>
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            // Because attached properties can come and go at any time,
            // the set of properties we have here always needs to be rebuilt.

            // We have two code paths here based on filtered attributes.  An attribute
            // filter is just a notificaiton of a filter, it doesn't actually perform
            // the filter.  Because the default PropertyFilterAttribute is PropertyFilter.All,
            // it acts as a nice "don't care" in later filtering stages that TypeDescriptor
            // may apply.  That means that regardless of the filter value, we don't have
            // to fiddle with adding the attribute to the property descriptor.

            PropertyFilterOptions filter = PropertyFilterOptions.Valid | PropertyFilterOptions.SetValues;

            if (attributes != null)
            {
                foreach (Attribute attr in attributes)
                {
                    PropertyFilterAttribute filterAttr = attr as PropertyFilterAttribute;
                    if (filterAttr != null)
                    {
                        filter = filterAttr.Filter;
                        break;
                    }
                }
            }

            if (filter == PropertyFilterOptions.None)
            {
                return(PropertyDescriptorCollection.Empty);
            }

            // First, get the set of all known registered properties in the
            // app domain.  GetRegisteredProperties caches its results and
            // will automatically re-fetch if new properties have been
            // registered
            DependencyProperty[] registeredProperties = GetRegisteredProperties();
            Type instanceType = _instance.GetType();

            // Next, walk through them and see which ones can be attached to this
            // object.  If our filter is specifically SetValues, we can
            // greatly shortcut the entire process by using the local value
            // enumerator.

            List <PropertyDescriptor> filteredProps;

            if (filter == PropertyFilterOptions.SetValues)
            {
                LocalValueEnumerator localEnum = _instance.GetLocalValueEnumerator();
                filteredProps = new List <PropertyDescriptor>(localEnum.Count);

                while (localEnum.MoveNext())
                {
                    DependencyProperty     dp   = localEnum.Current.Property;
                    DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);

                    // For locally set values, we just want to exclude direct and internal properties.
                    if (!kind.IsDirect && !kind.IsInternal)
                    {
                        DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
                        filteredProps.Add(dpProp);
                    }
                }
            }
            else
            {
                filteredProps = new List <PropertyDescriptor>(registeredProperties.Length);

                foreach (DependencyProperty dp in registeredProperties)
                {
                    bool addProp = false;
                    DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);

                    if (kind.IsAttached)
                    {
                        // Check bit combinations that would yield true in
                        // any case.  For non-attached properties, they're all valid, so if
                        // the valid bit is set, we're done.

                        PropertyFilterOptions anySet   = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues;
                        PropertyFilterOptions anyValid = PropertyFilterOptions.Valid | PropertyFilterOptions.Invalid;

                        if ((filter & anySet) == anySet || (filter & anyValid) == anyValid)
                        {
                            addProp = true;
                        }

                        if (!addProp && (filter & anyValid) != 0)
                        {
                            bool canAttach = CanAttachProperty(dp, _instance);
                            addProp = canAttach ^ ((filter & anyValid) == PropertyFilterOptions.Invalid);
                        }


                        if (!addProp && (filter & anySet) != 0)
                        {
                            bool shouldSerialize = _instance.ContainsValue(dp);
                            addProp = shouldSerialize ^ ((filter & anySet) == PropertyFilterOptions.UnsetValues);
                        }
                    }
                    else if ((filter & PropertyFilterOptions.SetValues) != 0 && _instance.ContainsValue(dp) && !kind.IsDirect && !kind.IsInternal)
                    {
                        // The property is not attached.  However, it isn't an internal DP and the user
                        // has requested set values.  See if the property is set on the object and include
                        // it if it is.
                        addProp = true;
                    }

                    if (addProp)
                    {
                        DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
                        filteredProps.Add(dpProp);
                    }
                }
            }

            PropertyDescriptorCollection properties;

            properties = new PropertyDescriptorCollection(filteredProps.ToArray(), true);
            return(properties);
        }
Beispiel #6
0
        private ArrayList SaveSubStreams(UIElement element)
        {
            ArrayList subStreams = null;

#pragma warning disable 618
            if ((element != null) && (element.PersistId != 0))
#pragma warning restore 618
            {
                LocalValueEnumerator dpEnumerator = element.GetLocalValueEnumerator();

                while (dpEnumerator.MoveNext())
                {
                    LocalValueEntry           localValueEntry = (LocalValueEntry)dpEnumerator.Current;
                    FrameworkPropertyMetadata metadata        = localValueEntry.Property.GetMetadata(element.DependencyObjectType) as FrameworkPropertyMetadata;

                    if (metadata == null)
                    {
                        continue;
                    }

                    // To be saved, a DP should have the correct metadata and NOT be an expression or data bound.
                    // Since Bind inherits from Expression, the test for Expression will suffice.
                    // NOTE: we do not journal expression. So we should let parser restore it in BamlRecordReader.SetDependencyValue.
                    // Please see Windows OS
                    if (metadata.Journal && (!(localValueEntry.Value is Expression)))
                    {
                        // These properties should not be journaled.
                        //

                        if (object.ReferenceEquals(localValueEntry.Property, Frame.SourceProperty))
                        {
                            continue;
                        }

                        if (subStreams == null)
                        {
                            subStreams = new ArrayList(3);
                        }

                        object currentValue = element.GetValue(localValueEntry.Property);
                        byte[] bytes        = null;

                        if ((currentValue != null) && !(currentValue is Uri))
                        {
                            // Convert the value of the DP into a byte array
                            MemoryStream byteStream = new MemoryStream();
                            new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert();
                            try
                            {
                                this.Formatter.Serialize(byteStream, currentValue);
                            }
                            finally
                            {
                                SecurityPermission.RevertAssert();
                            }

                            bytes = byteStream.ToArray();
                            // Dispose the stream
                            ((IDisposable)byteStream).Dispose( );
                        }

                        // Save the byte array by the property name
                        subStreams.Add(new SubStream(localValueEntry.Property.Name, bytes));
                    }
                }
            }

            return(subStreams);
        }
Beispiel #7
0
        private void GenerateBehaviorActions(ActionCollection actionCollection, CodeTypeDeclaration classType, CodeMemberMethod method, CodeVariableReferenceExpression behaviorVarRef, string behaviorName)
        {
            for (int i = 0; i < actionCollection.Count; i++)
            {
                var    action     = actionCollection[i];
                string actionName = behaviorName + "_ACT_" + i;
                Type   type       = action.GetType();

                CodeVariableDeclarationStatement variable = new CodeVariableDeclarationStatement(type.Name, actionName, new CodeObjectCreateExpression(type.Name));
                method.Statements.Add(variable);
                var actionVarRef = new CodeVariableReferenceExpression(actionName);

                method.Statements.Add(new CodeMethodInvokeExpression(
                                          behaviorVarRef, "Actions.Add", actionVarRef));

                ValueGenerator valueGenerator      = new ValueGenerator();
                MethodInfo     generateFieldMethod = typeof(CodeComHelper).GetMethod("GenerateField");

                LocalValueEnumerator enumerator = action.GetLocalValueEnumerator();
                while (enumerator.MoveNext())
                {
                    LocalValueEntry    entry    = enumerator.Current;
                    DependencyProperty property = entry.Property;
                    Type valueType = entry.Value.GetType();
                    if (CodeComHelper.IsValidForFieldGenerator(entry.Value))
                    {
                        if (valueGenerator.Generators.ContainsKey(property.PropertyType) || valueGenerator.Generators.ContainsKey(valueType))
                        {
                            CodeExpression propValue = valueGenerator.ProcessGenerators(classType, method, entry.Value, actionName);
                            if (propValue != null)
                            {
                                method.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(actionVarRef, property.Name), propValue));
                            }
                        }
                        else if (entry.Value is PropertyPath)
                        {
                            PropertyPath path = entry.Value as PropertyPath;
                            method.Statements.Add(new CodeAssignStatement(
                                                      new CodeFieldReferenceExpression(actionVarRef, property.Name),
                                                      new CodeObjectCreateExpression("PropertyPath", new CodePrimitiveExpression(path.Path))));
                        }
                        else if (entry.Value is SoundSource)
                        {
                            var soundSource = CodeComHelper.GenerateSoundSource(method, entry.Value as SoundSource);
                            method.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(actionVarRef, property.Name), soundSource));
                        }
                        else
                        {
                            MethodInfo generic = generateFieldMethod.MakeGenericMethod(property.PropertyType);
                            if (generic == null)
                            {
                                throw new NullReferenceException("Generic method not created for type - " + property.PropertyType);
                            }

                            generic.Invoke(null, new object[] { method, actionVarRef, action, property });
                        }
                    }
                }

                CodeComHelper.GenerateBindings(method, actionVarRef, action, actionName, behaviorVarRef);
                //CodeComHelper.GenerateResourceReferences(method, actionVarRef, action);
            }
        }
        /// <summary>
        /// Event handler for KeyDown event to auto-detect hyperlinks on space, enter and backspace keys.
        /// </summary>
        private static void OnKeyDown(object sender, KeyEventArgs e)
        {
            var myRichTextBox = (MyRichTextBox)sender;

            if (e.Key != Key.Space && e.Key != Key.Back && e.Key != Key.Return)
            {
                return;
            }

            if (!myRichTextBox.Selection.IsEmpty)
            {
                myRichTextBox.Selection.Text = String.Empty;
            }

            TextPointer caretPosition = myRichTextBox.Selection.Start;

            if (e.Key == Key.Space || e.Key == Key.Return)
            {
                TextPointer wordStartPosition;
                string      word = GetPreceedingWordInParagraph(caretPosition, out wordStartPosition);

                if (word == "www.microsoft.com")
                // A real app would need a more sophisticated RegEx match expression for hyperlinks.
                {
                    // Insert hyperlink element at word boundaries.
                    var start = wordStartPosition.GetPositionAtOffset(0, LogicalDirection.Backward);
                    var end   = caretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);

                    if (start != null)
                    {
                        if (end != null)
                        {
                            new Hyperlink(start
                                          , end);
                        }
                    }

                    // No need to update RichTextBox caret position,
                    // since we only inserted a Hyperlink ElementEnd following current caretPosition.
                    // Subsequent handling of space input by base RichTextBox will update selection.
                }
            }
            else // Key.Back
            {
                TextPointer backspacePosition = caretPosition.GetNextInsertionPosition(LogicalDirection.Backward);
                Hyperlink   hyperlink;
                if (backspacePosition != null &&
                    IsHyperlinkBoundaryCrossed(caretPosition, backspacePosition, out hyperlink))
                {
                    // Remember caretPosition with forward gravity. This is necessary since we are going to delete
                    // the hyperlink element preceeding caretPosition and after deletion current caretPosition
                    // (with backward gravity) will follow content preceeding the hyperlink.
                    // We want to remember content following the hyperlink to set new caret position at.

                    TextPointer newCaretPosition = caretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);

                    // Deleting the hyperlink is done using logic below.

                    // 1. Copy its children Inline to a temporary array.
                    InlineCollection hyperlinkChildren = hyperlink.Inlines;
                    var inlines = new Inline[hyperlinkChildren.Count];
                    hyperlinkChildren.CopyTo(inlines, 0);

                    // 2. Remove each child from parent hyperlink element and insert it after the hyperlink.
                    for (int i = inlines.Length - 1; i >= 0; i--)
                    {
                        hyperlinkChildren.Remove(inlines[i]);
                        if (hyperlink.SiblingInlines != null)
                        {
                            hyperlink.SiblingInlines.InsertAfter(hyperlink, inlines[i]);
                        }
                    }

                    // 3. Apply hyperlink's local formatting properties to inlines (which are now outside hyperlink scope).
                    LocalValueEnumerator localProperties = hyperlink.GetLocalValueEnumerator();
                    var inlineRange = new TextRange(inlines[0].ContentStart, inlines[inlines.Length - 1].ContentEnd);

                    while (localProperties.MoveNext())
                    {
                        LocalValueEntry    property = localProperties.Current;
                        DependencyProperty dp       = property.Property;
                        object             value    = property.Value;

                        if (!dp.ReadOnly &&
                            dp != Inline.TextDecorationsProperty && // Ignore hyperlink defaults.
                            dp != TextElement.ForegroundProperty &&
                            !IsHyperlinkProperty(dp))
                        {
                            inlineRange.ApplyPropertyValue(dp, value);
                        }
                    }

                    // 4. Delete the (empty) hyperlink element.
                    if (hyperlink.SiblingInlines != null)
                    {
                        hyperlink.SiblingInlines.Remove(hyperlink);
                    }

                    // 5. Update selection, since we deleted Hyperlink element and caretPosition was at that Hyperlink's end boundary.
                    if (newCaretPosition != null)
                    {
                        myRichTextBox.Selection.Select(newCaretPosition, newCaretPosition);
                    }
                }
            }
        }
Beispiel #9
0
        // Copies a LocalValueEnumerator properties into an array of DependencyProperty. 
        // This method is useful because LocalValueEnumerator does not support 
        // setting or clearing local values while enumerating.
        private DependencyProperty[] LocalValueEnumeratorToArray(LocalValueEnumerator valuesEnumerator) 
        {
            DependencyProperty[] properties;
            int count;
 
            properties = new DependencyProperty[valuesEnumerator.Count];
 
            count = 0; 
            valuesEnumerator.Reset();
            while (valuesEnumerator.MoveNext()) 
            {
                properties[count++] = valuesEnumerator.Current.Property;
            }
 
            return properties;
        } 
Beispiel #10
0
        /// <summary> 
        /// Sets local values on the text element scoping position.
        /// </summary>
        /// <param name="position">
        /// A position scoped by the element on which to set the property. 
        /// </param>
        /// <param name="values"> 
        /// Values to set. 
        /// </param>
        /// <exception cref="System.InvalidOperationException"> 
        /// Throws InvalidOperationException if position is not scoped by a
        /// text element or if a property value may not be applied on the
        /// scoping text element.
        /// </exception> 
        internal void SetValues(TextPointer position, LocalValueEnumerator values)
        { 
            TextElement textElement; 
            LocalValueEntry property;
 
//             VerifyAccess();

            if (position == null)
            { 
                throw new ArgumentNullException("position");
            } 
 
            // LocalValueEnumerator is a struct.
            // if (values == null) 
            // {
            //     throw new ArgumentNullException("values");
            // }
 
            EmptyDeadPositionList();
 
            ValidateSetValue(position); 

            BeginChange(); 
            try
            {
                textElement = position.Parent as TextElement;
                Invariant.Assert(textElement != null); 

                values.Reset(); 
                while (values.MoveNext()) 
                {
                    property = values.Current; 

                    //

 

 
 

 

                    if (property.Property.Name == "CachedSource")
                    {
                        continue; 
                    }
 
                    // If the property is readonly on the text element, then we shouldn't 
                    // try to copy the property value.
                    if (property.Property.ReadOnly) 
                    {
                        continue;
                    }
 
                    // Don't copy over Run.Text. This will get automatically invalidated by TextContainer
                    // when the Run's text content is set. Setting this property now will cause TextContainer 
                    // changes that get us into trouble in the middle of undo. 
                    if (property.Property == Run.TextProperty)
                    { 
                        continue;
                    }

                    BindingExpressionBase expr = property.Value as BindingExpressionBase; 
                    if (expr != null)
                    { 
                        // We can't duplicate a binding so copy over the current value instead. 
                        textElement.SetValue(property.Property, expr.Value);
                    } 
                    else
                    {
                        textElement.SetValue(property.Property, property.Value);
                    } 
                }
            } 
            finally 
            {
                EndChange(); 
            }
        }
Beispiel #11
0
        /// <summary>
        /// Validates a WPF tree to determine if binding errors exist
        /// </summary>
        /// <param name="parent">Parent DependencyObject</param>
        /// <returns>True if no errors exist</returns>
        public static bool IsValid(DependencyObject parent)
        {
            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }

            // note that this goes wrong in a data template
            // http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/d88f3926-68e5-488d-9fb1-a9f94a5ffd11
            // http://stackoverflow.com/questions/338522/getlocalvalueenumerator-not-returning-all-properties

            bool valid = true;

            // validate parent
            LocalValueEnumerator localValueEnumerator = parent.GetLocalValueEnumerator();

            while (localValueEnumerator.MoveNext())
            {
                LocalValueEntry entry = localValueEnumerator.Current;

                if (BindingOperations.IsDataBound(parent, entry.Property))
                {
                    Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                    if (binding.Path.Path.Contains("Search"))
                    {
                        Debug.WriteLine("Search");
                    }
                    if ((binding.Mode == BindingMode.TwoWay) || (binding.Mode == BindingMode.OneWayToSource))
                    {
                        BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                        expression.UpdateSource();
                        if (expression.HasError)
                        {
                            valid = false;
                        }
                    }
                }
            }

            // validate logical children
            bool        foundLogicalChildren = false;
            IEnumerable children             = LogicalTreeHelper.GetChildren(parent);

            foreach (object obj in children)
            {
                foundLogicalChildren = true;

                DependencyObject child = obj as DependencyObject;
                if (child != null)
                {
                    if (!IsValid(child))
                    {
                        valid = false;
                    }
                }
            }

            // if no logical children found try looking for visual children
            if ((!foundLogicalChildren) && (parent is Visual))
            {
                int visualChildrenCount = VisualTreeHelper.GetChildrenCount(parent);
                if (visualChildrenCount > 0)
                {
                    for (int child = 0; child < visualChildrenCount; child++)
                    {
                        if (!IsValid(VisualTreeHelper.GetChild(parent, child)))
                        {
                            valid = false;
                        }
                    }
                }
            }

            return(valid);
        }
        private void RemoveHyperlinkFormat()
        {
            TextPointer caretPosition     = Selection.Start;
            TextPointer backspacePosition = caretPosition.GetNextInsertionPosition(LogicalDirection.Backward);
            Hyperlink   hyperlink         = default(Hyperlink);

            try
            {
                if (backspacePosition != null && IsHyperlinkBoundaryCrossed(caretPosition, backspacePosition, ref hyperlink))
                {
                    // Remember caretPosition with forward gravity. This is necessary since we are going to delete
                    // the hyperlink element preceding caretPosition and after deletion current caretPosition
                    // (with backward gravity) will follow content preceding the hyperlink.
                    // We want to remember content following the hyperlink to set new caret position at.

                    TextPointer newCaretPosition = caretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);

                    // 1. Copy its children Inline to a temporary array
                    InlineCollection hyperlinkChildren = hyperlink.Inlines;
                    Inline[]         inlines           = new Inline[hyperlinkChildren.Count];
                    hyperlinkChildren.CopyTo(inlines, 0);

                    // 2. Remove each child from parent hyperlink element and insert it after the hyperlink
                    for (int i = inlines.Length - 1; i >= 0; i--)
                    {
                        hyperlinkChildren.Remove(inlines[i]);
                        if (hyperlink.SiblingInlines != null)
                        {
                            hyperlink.SiblingInlines.InsertAfter(hyperlink, inlines[i]);
                        }
                    }

                    // 3. Apply hyperlink local formatting properties to inlines (which are now outside hyperlink scope)
                    LocalValueEnumerator localProperties = hyperlink.GetLocalValueEnumerator();
                    TextRange            inlineRange     = new TextRange(inlines[0].ContentStart, inlines[inlines.Length - 1].ContentEnd);

                    while (localProperties.MoveNext())
                    {
                        LocalValueEntry    property           = localProperties.Current;
                        DependencyProperty dependencyProperty = property.Property;
                        object             value = property.Value;

                        // Ignore hyperlink defaults
                        if (dependencyProperty.ReadOnly == false &&
                            dependencyProperty.Equals(Inline.TextDecorationsProperty) == false &&
                            dependencyProperty.Equals(TextElement.ForegroundProperty) == false &&
                            dependencyProperty.Equals(BaseUriHelper.BaseUriProperty) == false &&
                            IsHyperlinkProperty(dependencyProperty) == false &&
                            dependencyProperty.Name.Equals("IsEnabled") == false)
                        {
                            inlineRange.ApplyPropertyValue(dependencyProperty, value);
                        }
                    }

                    // 4. Delete the (empty) hyperlink element
                    if (hyperlink.SiblingInlines != null)
                    {
                        hyperlink.RequestNavigate -= OnRequestNavigate;
                        hyperlink.SiblingInlines.Remove(hyperlink);
                    }

                    // 5. Update selection, since we deleted Hyperlink element and caretPosition was at that hyperlink's end boundary
                    Selection.Select(newCaretPosition, newCaretPosition);
                }
            }
            catch (Exception ex)
            {
                Log.Error("Error while removing hyperlink format: {EX}", ex);
            }
        }