Esempio n. 1
0
        public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
        {
            // A component might be in the render queue already before getting disposed by an
            // earlier entry in the render queue. In that case, rendering is a no-op.
            if (_componentWasDisposed)
            {
                return;
            }

            // Swap the old and new tree builders
            (CurrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrentRenderTree);

            CurrentRenderTree.Clear();
            renderFragment(CurrentRenderTree);

            var diff = RenderTreeDiffBuilder.ComputeDiff(
                _renderer,
                batchBuilder,
                ComponentId,
                _renderTreeBuilderPrevious.GetFrames(),
                CurrentRenderTree.GetFrames());

            batchBuilder.UpdatedComponentDiffs.Append(diff);
            batchBuilder.InvalidateParameterViews();
        }
Esempio n. 2
0
        public static void UpdateToMatchClientState(RenderTreeBuilder renderTreeBuilder, ulong eventHandlerId, object newFieldValue)
        {
            // We only allow the client to supply string or bool currently, since those are the only kinds of
            // values we output on attributes that go to the client
            if (!(newFieldValue is string || newFieldValue is bool))
            {
                return;
            }

            // Find the element that contains the event handler
            var frames                   = renderTreeBuilder.GetFrames();
            var framesArray              = frames.Array;
            var framesLength             = frames.Count;
            var closestElementFrameIndex = -1;

            for (var frameIndex = 0; frameIndex < framesLength; frameIndex++)
            {
                ref var frame = ref framesArray[frameIndex];
                switch (frame.FrameTypeField)
                {
                case RenderTreeFrameType.Element:
                    closestElementFrameIndex = frameIndex;
                    break;

                case RenderTreeFrameType.Attribute:
                    if (frame.AttributeEventHandlerIdField == eventHandlerId)
                    {
                        if (!string.IsNullOrEmpty(frame.AttributeEventUpdatesAttributeNameField))
                        {
                            UpdateFrameToMatchClientState(
                                renderTreeBuilder,
                                framesArray,
                                closestElementFrameIndex,
                                frame.AttributeEventUpdatesAttributeNameField,
                                newFieldValue);
                        }

                        // Whether or not we did update the frame, that was the one that matches
                        // the event handler ID, so no need to look any further
                        return;
                    }
                    break;
                }
            }
Esempio n. 3
0
        public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, out Exception?renderFragmentException)
        {
            renderFragmentException = null;

            // A component might be in the render queue already before getting disposed by an
            // earlier entry in the render queue. In that case, rendering is a no-op.
            if (_componentWasDisposed)
            {
                return;
            }

            _nextRenderTree.Clear();

            try
            {
                renderFragment(_nextRenderTree);
            }
            catch (Exception ex)
            {
                // If an exception occurs in the render fragment delegate, we won't process the diff in any way, so child components,
                // event handlers, etc., will all be left untouched as if this component didn't re-render at all. The Renderer will
                // then forcibly clear the descendant subtree by rendering an empty fragment for this component.
                renderFragmentException = ex;
                return;
            }

            // We don't want to make errors from this be recoverable, because there's no legitimate reason for them to happen
            _nextRenderTree.AssertTreeIsValid(Component);

            // Swap the old and new tree builders
            (CurrentRenderTree, _nextRenderTree) = (_nextRenderTree, CurrentRenderTree);

            var diff = RenderTreeDiffBuilder.ComputeDiff(
                _renderer,
                batchBuilder,
                ComponentId,
                _nextRenderTree.GetFrames(),
                CurrentRenderTree.GetFrames());

            batchBuilder.UpdatedComponentDiffs.Append(diff);
            batchBuilder.InvalidateParameterViews();
        }