Skip to content

feat(DockView): add OnlyWhenVisible render mode#974

Merged
ArgoZhang merged 53 commits intomasterfrom
dev-dockview-only
Apr 17, 2026
Merged

feat(DockView): add OnlyWhenVisible render mode#974
ArgoZhang merged 53 commits intomasterfrom
dev-dockview-only

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Apr 17, 2026

Link issues

fixes #973

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Introduce a visibility-driven rendering mode for DockViewV2 and synchronize dock panel state between Blazor components and the underlying JavaScript dockview instance.

New Features:

  • Add support for the OnlyWhenVisible render mode, allowing DockView components to render content only when their panels are visible and active.
  • Track per-component dock state (visibility and lock status) on the server side and expose callbacks for visibility, lock, splitter resize, and initialization events.
  • Highlight the first visible dock group item in the UI to adjust splitter styling based on visibility.

Enhancements:

  • Refine DockView JavaScript integration to drive tab loading, panel creation/removal, and template movement based on render mode and local storage configuration.
  • Simplify render mode options by removing the Partial mode and consolidating behavior into Always and OnlyWhenVisible.
  • Improve XML documentation and localization comments across DockView-related components for clearer API usage.

Copilot AI review requested due to automatic review settings April 17, 2026 11:41
@bb-auto bb-auto bot added the enhancement New feature or request label Apr 17, 2026
@bb-auto bb-auto bot added this to the v9.2.0 milestone Apr 17, 2026
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 17, 2026

Reviewer's Guide

Implements an "OnlyWhenVisible" render mode for DockViewV2 by tracking per-component state on the server and wiring it to updated JavaScript lifecycle events so that Blazor components are only rendered when their panels are visible, while also refining DockView configuration, callbacks, and related UI behavior and docs.

Sequence diagram for OnlyWhenVisible DockView rendering and visibility updates

sequenceDiagram
    actor User
    participant Browser
    participant DockviewJS
    participant DotNetRuntime
    participant DockViewV2
    participant DockViewComponent
    participant DockViewComponentState

    User->>Browser: Open page with DockViewV2
    Browser->>DockviewJS: init(options)
    DockviewJS->>DockviewJS: load layout from JSON / storage

    Note over DockviewJS: After layout applied
    DockviewJS->>DockviewJS: compute visiblePanels
    DockviewJS->>DockviewJS: _loadTabs.fire(visiblePanelKeys)
    DockviewJS->>DotNetRuntime: invokeMethodAsync(loadTabs, tabs)
    DotNetRuntime->>DockViewV2: LoadTabs(List~string~ tabs)
    DockViewV2->>DockViewV2: _loadTabs = tabs.ToHashSet()
    DockViewV2->>DockViewV2: for each componentState
    DockViewV2->>DockViewComponentState: set Render based on tabs.Contains(key)
    DockViewV2->>DockViewV2: StateHasChanged()

    Note over DockViewComponent: during render
    DockViewComponent->>DockViewV2: IsRender(Key)
    DockViewV2->>DockViewV2: Renderer switch
    DockViewV2-->>DockViewComponent: OnlyWhenVisible => state.IsRender()
    DockViewComponent->>DockViewComponent: if IsRender() true render ChildContent

    Note over User,Browser: User changes tab visibility

    User->>Browser: Hide/show or close a panel
    Browser->>DockviewJS: Panel visibility change
    DockviewJS->>DockviewJS: _panelVisibleChanged.fire({key,status})
    DockviewJS->>DotNetRuntime: invokeMethodAsync(panelVisibleChangedCallback, key, status)
    DotNetRuntime->>DockViewV2: PanelVisibleChangedCallbackAsync(string key, bool status)
    DockViewV2->>DockViewV2: lookup DockViewComponentState by key
    DockViewV2->>DockViewComponentState: Visible = status
    DockViewV2->>DockViewComponent: Component.SetVisible(status)
    DockViewV2->>DockViewV2: optionally invoke OnVisibleStateChangedAsync

    Note over DockViewComponent: on next render
    DockViewComponent->>DockViewV2: IsRender(Key)
    DockViewV2-->>DockViewComponent: returns state.IsRender() (Visible && Render)
Loading

Updated class diagram for DockView OnlyWhenVisible render mode

classDiagram
    class DockViewV2 {
        +string Name
        +string LayoutConfig
        +bool ShowClose
        +bool IsLock
        +bool ShowLock
        +bool ShowMaximize
        +bool IsFloating
        +bool ShowFloat
        +bool ShowPin
        +DockViewRenderMode Renderer
        +Func~string[],bool,Task~ OnLockChangedCallbackAsync
        +Func~string,bool,Task~ OnVisibleStateChangedAsync
        +Func~Task~ OnSplitterCallbackAsync
        +Func~Task~ OnInitializedCallbackAsync
        +RenderFragment ChildContent
        +string Version
        +bool? EnableLocalStorage
        +string LocalStoragePrefix
        +DockViewTheme Theme
        -DockViewV2 DockView
        -DockViewOptions _options
        -ConcurrentDictionary~string,DockViewComponentState~ _componentStates
        -HashSet~string~ _loadTabs
        +Task Reset(string layoutConfig)
        +Task~string~ SaveLayout()
        +Task InitializedCallbackAsync()
        +Task PanelVisibleChangedCallbackAsync(string key, bool status)
        +Task LockChangedCallbackAsync(string[] panels, bool locked)
        +Task SplitterCallbackAsync()
        +Task LoadTabs(List~string~ tabs)
        +void AddComponentState(DockViewComponentState state)
        +void RemoveComponentState(string key)
        +void UpdateComponentState(string key, bool visible, bool? isLock)
        +bool IsRender(string key)
    }

    class DockViewComponentBase {
        <<abstract>>
        +DockViewContentType Type
        +int? Width
        +int? Height
        +RenderFragment ChildContent
        -List~DockViewComponentBase~ Parent
        +void Dispose()
        #void Dispose(bool disposing)
    }

    class DockViewComponent {
        +bool ShowHeader
        +string Title
        +int? TitleWidth
        +string TitleClass
        +RenderFragment TitleTemplate
        +string Class
        +bool Visible
        +bool? ShowClose
        +string Key
        +bool? IsLock
        +bool? ShowLock
        +bool? IsFloating
        +bool? ShowFloat
        +bool? ShowMaximize
        +string Renderer
        +bool ShowTitleBar
        +string TitleBarIcon
        +string TitleBarIconUrl
        +Func~Task~ OnClickTitleBarCallback
        -DockViewV2 DockView
        +void SetVisible(bool visible)
        +void SetLock(bool isLock)
        +bool IsRender()
        +void Dispose(bool disposing)
    }

    class DockViewComponentState {
        +string Key
        +bool? IsLock
        +bool Visible
        +bool Render
        +DockViewComponent Component
    }

    class DockViewComponentStateExtensions {
        +bool IsRender()
    }

    class DockViewConfig {
        +bool EnableLocalStorage
        +bool IsLock
        +bool ShowLock
        +bool IsFloating
        +bool ShowFloat
        +bool ShowClose
        +bool ShowPin
        +bool ShowMaximize
        +DockViewRenderMode Renderer
        +string PanelVisibleChangedCallback
        +string InitializedCallback
        +string LockChangedCallback
        +string SplitterCallback
        +string LoadTabs
        +string LocalStorageKey
        +List~DockViewComponentBase~ Contents
        +string Theme
        +string LayoutConfig
    }

    class DockViewOptions {
        +string Version
        +bool? EnableLocalStorage
        +string LocalStoragePrefix
    }

    class DockViewContent {
        +List~DockViewComponentBase~ Contents
    }

    DockViewComponentBase <|-- DockViewComponent
    DockViewComponentBase <|-- DockViewContent

    DockViewV2 "1" o-- "many" DockViewComponentState : tracks
    DockViewComponentState "1" --> "1" DockViewComponent : Component

    DockViewComponent "many" --> "1" DockViewV2 : CascadingParameter

    DockViewV2 --> DockViewConfig : builds
    DockViewV2 --> DockViewOptions : reads

    DockViewConfig --> DockViewComponentBase : contents

    DockViewComponentStateExtensions ..> DockViewComponentState : extension
Loading

File-Level Changes

Change Details Files
Add server-side component state tracking and OnlyWhenVisible render logic for DockViewV2 and DockViewComponent.
  • Introduce DockViewComponentState and extension helpers to track per-component key, visibility, lock, and render flags.
  • Maintain a ConcurrentDictionary of DockViewComponentState in DockViewV2 and expose internal methods to add, remove, update states and determine if a component should render.
  • Update DockViewComponent to register itself with DockViewV2, synchronize its Visible/IsLock parameters into shared state, decide rendering via IsRender, and clean up its state on dispose.
  • Change SaveLayout and callback signatures/JSInvokable methods in DockViewV2 to use keys instead of titles and to drive state updates on lock/visibility/splitter events.
  • Remove the obsolete Partial render mode from DockViewRenderMode, leaving Always and OnlyWhenVisible as the supported options.
src/components/BootstrapBlazor.DockView/Data/DockViewComponentState.cs
src/components/BootstrapBlazor.DockView/Extensions/DockViewComponentStateExtensions.cs
src/components/BootstrapBlazor.DockView/Components/DockViewV2.razor.cs
src/components/BootstrapBlazor.DockView/Components/DockViewComponent.razor.cs
src/components/BootstrapBlazor.DockView/Components/DockViewComponent.razor
src/components/BootstrapBlazor.DockView/Components/DockViewRenderMode.cs
Align and enhance JavaScript integration for panel visibility, layout loading, and panel lifecycle under OnlyWhenVisible.
  • Adjust dockview-utils initialization to fire panelVisibleChanged events with panel keys, respect EnableLocalStorage when replaying visibility, and trigger loadTabs differently for OnlyWhenVisible vs Always renderers.
  • Modify toggleComponent logic to merge params from options into existing panels, add panels back into groups, and close or hide panels that are no longer configured, optionally moving them back to the template container.
  • Refactor docking group helpers so addGroupWithPanel/addPanelWidthCreatGroup no longer emit visibility events directly and rely on new closePanel logic.
  • Extend DockviewGroupPanelModel.closePanel to emit key-based visibility events and optionally move panel DOM back to the template; update DockviewComponent.setVisible to mark the first visible element via markFirstVisibleElement.
  • Update panel observers so OnlyWhenVisible groups unload inactive panel DOM, and make visibility-change handlers compute visible panels lazily; comment out previous template-append logic in onRemovePanel.
  • Introduce markFirstVisibleElement helper and CSS to adjust vertical splitter bar height for the first visible panel in a group.
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js
src/components/BootstrapBlazor.DockView/wwwroot/css/dockview-bb.css
src/components/BootstrapBlazor.DockView/Components/DockViewV2.razor.js
Polish DockView configuration, documentation comments, and minor APIs.
  • Standardize and clarify XML doc comments in both Chinese and English across DockViewV2, DockViewComponent, DockViewComponentBase, DockViewConfig, DockViewOptions, DockViewTitleBar, DockViewIcon, DockViewContent, and DockViewComponentConverter.
  • Tweak DockViewV2 public callbacks to consistently describe visibility, lock, splitter and initialization semantics and rename some callback descriptions for clarity.
  • Update DockViewConfig and DockViewOptions docstrings and JSON attributes, and slightly adjust SaveLayout return type and other small API signatures.
  • Minor cleanup: remove unused parameters/comments, trim legacy commented-out JS code, and normalize formatting across JS/C# files.
src/components/BootstrapBlazor.DockView/Components/DockViewV2.razor.cs
src/components/BootstrapBlazor.DockView/Components/DockViewComponent.razor.cs
src/components/BootstrapBlazor.DockView/Components/DockViewComponentBase.cs
src/components/BootstrapBlazor.DockView/Components/DockViewConfig.cs
src/components/BootstrapBlazor.DockView/Components/DockViewOptions.cs
src/components/BootstrapBlazor.DockView/Components/DockViewTitleBar.razor.cs
src/components/BootstrapBlazor.DockView/Components/DockViewIcon.razor.cs
src/components/BootstrapBlazor.DockView/Components/DockViewContent.cs
src/components/BootstrapBlazor.DockView/Converters/DockViewComponentConverter.cs
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js

Assessment against linked issues

Issue Objective Addressed Explanation
#973 Add an OnlyWhenVisible render mode to the DockView component so that tab content is only rendered when the corresponding panel is visible, including all necessary .NET and JavaScript plumbing.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • The new DockViewComponentStateExtensions file doesn’t use valid C# extension method syntax (extension(DockViewComponentState? state)); this should be rewritten as a standard static extension method (e.g. public static bool IsRender(this DockViewComponentState? state)) to compile correctly.
  • In DockViewV2.SaveLayout you changed the InvokeAsync generic argument from string? to string but left the method signature as Task<string?>; align these nullability annotations so the return type and JS interop call agree.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new DockViewComponentStateExtensions file doesn’t use valid C# extension method syntax (`extension(DockViewComponentState? state)`); this should be rewritten as a standard static extension method (e.g. `public static bool IsRender(this DockViewComponentState? state)`) to compile correctly.
- In DockViewV2.SaveLayout you changed the `InvokeAsync` generic argument from `string?` to `string` but left the method signature as `Task<string?>`; align these nullability annotations so the return type and JS interop call agree.

## Individual Comments

### Comment 1
<location path="src/components/BootstrapBlazor.DockView/Extensions/DockViewComponentStateExtensions.cs" line_range="7-9" />
<code_context>
+
+namespace BootstrapBlazor.Components;
+
+static class DockViewComponentStateExtensions
+{
+    extension(DockViewComponentState? state)
+    {
+        /// <summary>
</code_context>
<issue_to_address>
**issue (bug_risk):** The `extension(DockViewComponentState? state)` syntax is not valid C# and will not compile.

To make this an extension method, declare a `public static` method with a `this` parameter inside a `public static` class, e.g.

```csharp
public static class DockViewComponentStateExtensions
{
    public static bool IsRender(this DockViewComponentState? state)
    {
        var render = false;
        if (state != null)
        {
            render = state.Render && state.Visible;
        }
        return render;
    }
}
```
Refactoring to this standard pattern will restore compilation and keep `IsRender()` usable from `DockViewV2`.
</issue_to_address>

### Comment 2
<location path="src/components/BootstrapBlazor.DockView/Components/DockViewV2.razor.cs" line_range="285" />
<code_context>
+        {
+            state.Visible = status;
+
+            // 同步可见状态到组件实例
+            state.Component.SetVisible(status);
+        }
</code_context>
<issue_to_address>
**nitpick (typo):** The comment inside LockChangedCallbackAsync refers to visibility but the code is updating lock state.

Consider updating the Chinese comment to better match the behavior, e.g. change it to “同步锁定状态到组件实例” so it accurately describes syncing the lock state to the component instance.

Suggested implementation:

```csharp
        {
            state.Locked = status;

            // 同步锁定状态到组件实例
            state.Component.SetLocked(status);
        }

```

If the method name or the component API differs (e.g., `SetLocked` has a different name, or the body uses `SetVisible(status)` instead of `SetLocked(status)`), adjust the SEARCH snippet accordingly so that the line immediately above the `SetLocked`/`SetVisible` call is the one with the outdated Chinese comment `// 同步可见状态到组件实例`. The only intended change is to update that comment text to `// 同步锁定状态到组件实例`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ArgoZhang ArgoZhang merged commit 7f88927 into master Apr 17, 2026
3 checks passed
@ArgoZhang ArgoZhang deleted the dev-dockview-only branch April 17, 2026 11:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an OnlyWhenVisible rendering mode for DockViewV2, aiming to render tab content only when the panel is visible/active, reducing DOM and render cost for large layouts.

Changes:

  • Introduces a Blazor-side component state cache to decide whether each DockViewComponent should render (OnlyWhenVisible).
  • Updates DockView JS interop/events to drive lazy tab rendering (loadTabs) and panel visibility notifications by key.
  • Adds supporting JS/CSS adjustments to manage visibility/layout edge cases (e.g., first visible split view styling).

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-utils.js Updates local-storage restore/visibility handling; fires loadTabs for OnlyWhenVisible
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-panel.js Triggers loadTabs when panel visibility changes
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-group.js Adjusts group/panel add logic and marks first visible elements
src/components/BootstrapBlazor.DockView/wwwroot/js/dockview-extensions.js Overrides dockview behaviors (panel close, setVisible); adds template move logic
src/components/BootstrapBlazor.DockView/wwwroot/css/dockview-bb.css Adds split-view pseudo-element rules for first visible behavior
src/components/BootstrapBlazor.DockView/Extensions/DockViewComponentStateExtensions.cs Adds IsRender helper for component render decisions
src/components/BootstrapBlazor.DockView/Data/DockViewComponentState.cs Adds a state model tracking Key/Visible/Render/Lock + component reference
src/components/BootstrapBlazor.DockView/Converters/DockViewComponentConverter.cs Documentation tweak
src/components/BootstrapBlazor.DockView/Components/DockViewV2.razor.js Updates JS callbacks (visibility changed by key; loadTabs invokes .NET)
src/components/BootstrapBlazor.DockView/Components/DockViewV2.razor.cs Implements state tracking + OnlyWhenVisible render decision logic
src/components/BootstrapBlazor.DockView/Components/DockViewTitleBar.razor.cs Doc updates (bilingual summaries)
src/components/BootstrapBlazor.DockView/Components/DockViewRenderMode.cs Keeps OnlyWhenVisible + Always (removes Partial)
src/components/BootstrapBlazor.DockView/Components/DockViewOptions.cs Doc updates (bilingual summaries)
src/components/BootstrapBlazor.DockView/Components/DockViewIcon.razor.cs Doc cleanup
src/components/BootstrapBlazor.DockView/Components/DockViewDropdownIcon.razor.cs Doc cleanup
src/components/BootstrapBlazor.DockView/Components/DockViewContent.cs Doc punctuation cleanup
src/components/BootstrapBlazor.DockView/Components/DockViewConfig.cs Adds docs + refines callback property docs
src/components/BootstrapBlazor.DockView/Components/DockViewComponentBase.cs Doc updates + minor cleanup
src/components/BootstrapBlazor.DockView/Components/DockViewComponent.razor.cs Registers component state; switches rendering decision to DockViewV2 state
src/components/BootstrapBlazor.DockView/Components/DockViewComponent.razor Renders child content based on IsRender() instead of Visible
src/components/BootstrapBlazor.DockView/BootstrapBlazor.DockView.csproj Bumps package version to 10.0.8-beta05

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +191 to +194
internal void SetVisible(bool visible) => Visible = visible;

internal void SetLock(bool isLock) => IsLock = isLock;

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous public SetVisible(bool) API appears to have been removed and replaced with internal setters (SetVisible/SetLock). If this library is consumed externally, that is a breaking change for callers that were driving visibility/lock state imperatively. Consider keeping the public methods (or introducing a new supported public API) and using internal helpers separately.

Suggested change
internal void SetVisible(bool visible) => Visible = visible;
internal void SetLock(bool isLock) => IsLock = isLock;
/// <summary>
/// <para lang="zh">设置组件显示状态</para>
/// <para lang="en">Sets the component visibility state</para>
/// </summary>
/// <param name="visible"></param>
public void SetVisible(bool visible) => SetVisibleCore(visible);
/// <summary>
/// <para lang="zh">设置组件锁定状态</para>
/// <para lang="en">Sets the component lock state</para>
/// </summary>
/// <param name="isLock"></param>
public void SetLock(bool isLock) => SetLockCore(isLock);
internal void SetVisibleCore(bool visible) => Visible = visible;
internal void SetLockCore(bool isLock) => IsLock = isLock;

Copilot uses AI. Check for mistakes.

DockviewGroupPanel.prototype.setParams = function (data) {
DockviewGroupPanel.prototype.setParams = function(data) {
console.log('setParameter', data);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DockviewGroupPanel.prototype.setParams contains a console.log debug statement. This will spam the console in production and can leak data. Please remove the log (or gate it behind an explicit debug flag).

Suggested change
console.log('setParameter', data);

Copilot uses AI. Check for mistakes.
Comment on lines +189 to +190
private bool IsRender() => DockView.IsRender(Key);

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsRender() calls DockView.IsRender(Key) but DockView is nullable. This can throw NullReferenceException if the cascading parameter is missing. Consider DockView?.IsRender(Key) ?? true (or a deterministic fallback) or enforce DockView presence earlier with a clear error.

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +25
extension(DockViewComponentState? state)
{
/// <summary>
/// <para lang="zh">判断组件是否需要渲染</para>
/// <para lang="en">Determine whether the component needs to be rendered</para>
/// </summary>
public bool IsRender()
{
// 如果组件 Visible false 表示组件不可见,此时 Render 也不需要渲染
var render = false;
if (state != null)
{
// 组件必须可见并且 Active 时才需要渲染
render = state.Render && state.Visible;
}
return render;
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file uses the new extension(DockViewComponentState? state) { ... } syntax, which depends on very recent/preview C# support. Since the repo sets <LangVersion>latest</LangVersion> (not explicitly preview), builds can break depending on the SDK. Prefer a conventional extension method (public static bool IsRender(this DockViewComponentState? state)).

Suggested change
extension(DockViewComponentState? state)
{
/// <summary>
/// <para lang="zh">判断组件是否需要渲染</para>
/// <para lang="en">Determine whether the component needs to be rendered</para>
/// </summary>
public bool IsRender()
{
// 如果组件 Visible false 表示组件不可见,此时 Render 也不需要渲染
var render = false;
if (state != null)
{
// 组件必须可见并且 Active 时才需要渲染
render = state.Render && state.Visible;
}
return render;
}
/// <summary>
/// <para lang="zh">判断组件是否需要渲染</para>
/// <para lang="en">Determine whether the component needs to be rendered</para>
/// </summary>
public static bool IsRender(this DockViewComponentState? state)
{
// 如果组件 Visible false 表示组件不可见,此时 Render 也不需要渲染
var render = false;
if (state != null)
{
// 组件必须可见并且 Active 时才需要渲染
render = state.Render && state.Visible;
}
return render;

Copilot uses AI. Check for mistakes.
Comment on lines 67 to +71
if (!panel.group.locked) {
removePanel.apply(this, args)
if (!this.isClearing) {
this._panelVisibleChanged?.fire({ title: panel.title, status: false });
closePanel.call(this, panel);
if (triggerVisibleChangedCallback) {
this.accessor._panelVisibleChanged?.fire({ key: panel.params.key, status: false });
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When panel.group.locked is true, this override skips calling the original closePanel, but the function continues afterward (including content moves). This can leave the panel visible while its content is detached. Gate the rest of the logic on a successful close.

Copilot uses AI. Check for mistakes.
/// <para lang="zh">获得/设置 标题模板,默认为 null</para>
/// <para lang="en">Gets or sets the title template. Default is null</para>
/// </summary>
[Parameter]
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TitleTemplate is a RenderFragment but it’s no longer marked with [JsonIgnore]. Since DockViewComponent instances are serialized into DockViewConfig.Contents for JS interop, this can cause System.Text.Json serialization to fail at runtime. Add [JsonIgnore] back for TitleTemplate (and any other non-serializable component parameters).

Suggested change
[Parameter]
[Parameter]
[JsonIgnore]

Copilot uses AI. Check for mistakes.
Comment on lines +175 to 179
base.OnParametersSet();

// 同步组件状态到缓存
DockView.UpdateComponentState(Key, Visible, IsLock);
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DockView is a nullable cascading parameter but is dereferenced without a null-check in OnParametersSet (DockView.UpdateComponentState(...)). If DockViewComponent is ever used outside a DockViewV2 (or cascading value is missing), this will throw. Either use DockView?.UpdateComponentState(...) or validate DockView once in OnInitialized and throw a clear exception.

Copilot uses AI. Check for mistakes.
{
_loadTabs.Add(tab);
// 标记是否渲染
componnet.Value.Render = tabs.Contains(componnet.Key);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadTabs creates a HashSet (_loadTabs = tabs.ToHashSet()), but then uses tabs.Contains(...) inside the loop. This defeats the purpose of the set and is O(n*m). Use _loadTabs.Contains(...) (or a local HashSet) for membership checks.

Suggested change
componnet.Value.Render = tabs.Contains(componnet.Key);
componnet.Value.Render = _loadTabs.Contains(componnet.Key);

Copilot uses AI. Check for mistakes.
Comment on lines +346 to 347
foreach (var componnet in _componentStates)
{
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in loop variable name componnet (should be component). This reduces readability and makes searching harder.

Copilot uses AI. Check for mistakes.
Comment on lines +307 to +311
{
state.IsLock = locked;

// 同步可见状态到组件实例
state.Component.SetLock(locked);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LockChangedCallbackAsync mutates component state (IsLock) and calls SetLock, but it doesn’t trigger any re-render. If lock state affects rendering/behavior on the Blazor side, this update won’t be reflected until another render occurs. Consider calling StateHasChanged() (or a more targeted update) after applying the lock changes.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(DockView): add OnlyWhenVisible render mode

3 participants