示例#1
0
        /// <summary>
        /// Attaches event listeners to elements that possess them.
        /// </summary>
        void Attach()
        {
            var evt = attributes.Event;

            if (evt == null)
            {
                return;
            }

            if (handler.Value == null)
            {
                throw new DOMTargetEventException(Element, Events.Error);
            }

            if (observer.Value == null)
            {
                throw new DOMTargetEventException(Element, Events.Error);
            }

            observer.Value.Register(
                evt,
                InterfaceEventListener.Create(InvokeHandleEvent),
                GetCapture());
        }
示例#2
0
        /// <summary>
        /// Dynamically generate repeat items, reusing existing instances if available.
        /// </summary>
        /// <returns></returns>
        public void Update()
        {
            // refresh binding
            if (Binding != null)
            {
                Binding.Recalculate();
            }

            // configure listener for instance alterations
            if (Binding != null &&
                Binding.Context != null)
            {
                if (listener == null)
                {
                    var target = Binding.Context.Instance.Element.Parent.Interface <EventTarget>();

                    // find existing listener
                    listener =
                        InterfaceEventListener.GetListener(target, Events.Insert, true, Update) ??
                        InterfaceEventListener.GetListener(target, Events.Delete, true, Update);

                    // register listener
                    if (listener == null)
                    {
                        listener = InterfaceEventListener.Create(Update);
                        target.Register(Events.Insert, listener, true);
                        target.Register(Events.Delete, listener, true);
                    }
                }
            }

            // store current index item
            var indexPrev = Index;
            var indexItem = Element
                            .Elements()
                            .FirstOrDefault(i => i.AnnotationOrCreate <RepeatItemState>().Index == Index);

            // build new list of properly ordered nodes
            var items = Binding != null?Binding.ModelItems.Select(i => i.Xml).ToArray() : new XObject[0];

            var nodes = Element.Elements().ToArray();
            var sorts = new XElement[items.Length];

            for (int index = 0; index < items.Length; index++)
            {
                // model item at current index
                var item = items[index];

                // get existing item or create new
                var indx = Array.FindIndex(nodes, i => i.AnnotationOrCreate <RepeatItemState>().ModelObjectId == item.GetObjectId());
                var node = indx >= 0 ? nodes[indx] : null;
                if (node == null)
                {
                    node = new XElement(
                        Constants.XForms_1_0 + "group",
                        Template.GetNamespacePrefixAttributes(),
                        Template.Nodes());
                }

                // set node into output list
                sorts[index] = node;

                // configure item state
                var anno = node.AnnotationOrCreate <RepeatItemState>();
                anno.ModelObjectId = item.GetObjectId();
                anno.Index         = index + 1;
                anno.Size          = items.Length;
            }

            // new sequence is different from old sequence
            if (sorts.Length != nodes.Length ||
                sorts.SequenceEqual(nodes) == false)
            {
                // replace all children
                Element.RemoveNodes();
                Element.Add(sorts);

                // set of elements that were added
                var added = sorts
                            .Except(nodes)
                            .ToArray();

                // model-construct-done sequence applied to new children
                foreach (var node in added)
                {
                    foreach (var i in GetAllExtensions <IOnRefresh>(node))
                    {
                        i.RefreshBinding();
                    }
                }

                // discard refresh events
                foreach (var node in added)
                {
                    foreach (var i in GetAllExtensions <IOnRefresh>(node))
                    {
                        i.DiscardEvents();
                    }
                }

                // final refresh
                foreach (var node in added)
                {
                    foreach (var i in GetAllExtensions <IOnRefresh>(node))
                    {
                        i.Refresh();
                    }
                }
            }

            // restore or reset index
            var length = Element.Elements().Count();

            if (indexItem != null &&
                indexItem.Parent != null)
            {
                Index = indexItem.AnnotationOrCreate <RepeatItemState>().Index;
            }
            else if (indexPrev > 0)
            {
                Index = indexPrev <= length ? indexPrev : length;
            }
            else if (length > 0)
            {
                Index = 1;
            }
            else
            {
                Index = 0;
            }
        }