diff --git a/src/BootstrapBlazor.Shared/Extensions/MenusLocalizerExtensions.cs b/src/BootstrapBlazor.Shared/Extensions/MenusLocalizerExtensions.cs
index 080bd903a0d..cda750cfd11 100644
--- a/src/BootstrapBlazor.Shared/Extensions/MenusLocalizerExtensions.cs
+++ b/src/BootstrapBlazor.Shared/Extensions/MenusLocalizerExtensions.cs
@@ -743,6 +743,11 @@ void AddDockView(DemoMenuItem item)
{
Text = Localizer["DockViewLock"],
Url = "dock-view/lock"
+ },
+ new()
+ {
+ Text = Localizer["DockViewLayout"],
+ Url = "dock-view/layout"
}
};
AddBadge(item, count: 1);
diff --git a/src/BootstrapBlazor.Shared/Locales/en.json b/src/BootstrapBlazor.Shared/Locales/en.json
index 338f0431740..49c70103371 100644
--- a/src/BootstrapBlazor.Shared/Locales/en.json
+++ b/src/BootstrapBlazor.Shared/Locales/en.json
@@ -4503,6 +4503,7 @@
"DockViewComplex": "Complex",
"DockViewVisible": "Visible",
"DockViewLock": "Lock",
+ "DockViewLayout": "Custom",
"OtherComponents": "Others",
"MouseFollowerIntro": "MouseFollower",
"Live2DDisplayIntro": "Live2D Widget",
diff --git a/src/BootstrapBlazor.Shared/Locales/zh.json b/src/BootstrapBlazor.Shared/Locales/zh.json
index 97cebe49ad3..f29ceb95e66 100644
--- a/src/BootstrapBlazor.Shared/Locales/zh.json
+++ b/src/BootstrapBlazor.Shared/Locales/zh.json
@@ -4503,6 +4503,7 @@
"DockViewComplex": "组合布局",
"DockViewVisible": "可见性切换",
"DockViewLock": "布局锁定",
+ "DockViewLayout": "布局自定义",
"OtherComponents": "其他组件",
"MouseFollowerIntro": "鼠标跟随",
"Live2DDisplayIntro": "Live2D 插件",
diff --git a/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor
new file mode 100644
index 00000000000..f013af87085
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor
@@ -0,0 +1,94 @@
+@page "/dock-view/layout"
+@inherits BaseDockView
+
+
自定义布局
+通过设置 DockView
的属性 LayoutConfig
初始化控制面板的显示布局, 方法 GetLayoutConfig
获取面板的显示布局
+
+
+
+
+
+
+
+ @LayoutConfigSave
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@code {
+ [NotNull]
+ private DockView? DockView { get; set; }
+
+ private async Task GetLayout()
+ {
+ LayoutConfigSave = await DockView.GetLayoutConfig();
+ }
+
+ private Task Reset() => DockView.Reset();
+
+ private void OnToggleLayout1()
+ {
+ LayoutConfig = LayoutConfig1;
+ }
+
+ private void OnToggleLayout2()
+ {
+ LayoutConfig = LayoutConfig2;
+ }
+
+ private void OnToggleLayout3()
+ {
+ LayoutConfig = LayoutConfig3;
+ }
+
+ string? LayoutConfig;
+
+ string? LayoutConfigSave;
+
+ string LayoutConfig1 = """"
+{"root":{"type":"row","content":[{"type":"column","content":[{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_45517422","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签三","componentType":"component","componentState":{"id":"bb_45517422","showClose":true,"class":null,"key":"标签三","lock":false}}],"width":50,"minWidth":0,"height":33.460076045627375,"minHeight":0,"id":"","isClosable":true,"maximised":false,"activeItemIndex":0},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_42425232","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签二","componentType":"component","componentState":{"id":"bb_42425232","showClose":true,"class":null,"key":"标签二","lock":false}}],"width":50,"minWidth":0,"height":66.53992395437263,"minHeight":0,"id":"","isClosable":true,"maximised":false,"activeItemIndex":0}],"width":50,"minWidth":50,"height":50,"minHeight":50,"id":"","isClosable":true},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_21184535","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签一","componentType":"component","componentState":{"id":"bb_21184535","showClose":true,"class":null,"key":"标签一","lock":false}}],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_54183781","isClosable":true,"maximised":false,"activeItemIndex":0}],"width":50,"minWidth":50,"height":50,"minHeight":50,"id":"","isClosable":true},"openPopouts":[],"settings":{"constrainDragToContainer":true,"reorderEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"responsiveMode":"none","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10,"popInOnClose":false},"dimensions":{"borderWidth":5,"borderGrabWidth":5,"minItemHeight":10,"minItemWidth":10,"headerHeight":25,"dragProxyWidth":300,"dragProxyHeight":200},"header":{"show":"top","popout":"lock/unlock","dock":"dock","close":"close","maximise":"maximise","minimise":"minimise","tabDropdown":"additional tabs"},"resolved":true}
+"""";
+
+ string LayoutConfig2 = """"
+{"root":{"type":"row","content":[{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_24636646","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签三","componentType":"component","componentState":{"id":"bb_24636646","showClose":true,"class":null,"key":"标签三","lock":false}}],"width":33.333333333333336,"minWidth":0,"height":50,"minHeight":0,"id":"","isClosable":true,"maximised":false,"activeItemIndex":0},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_60600063","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签一","componentType":"component","componentState":{"id":"bb_60600063","showClose":true,"class":null,"key":"标签一","lock":false}}],"width":33.333333333333336,"minWidth":0,"height":50,"minHeight":0,"id":"bb_54183781","isClosable":true,"maximised":false,"activeItemIndex":0},{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_6744750","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签二","componentType":"component","componentState":{"id":"bb_6744750","showClose":true,"class":null,"key":"标签二","lock":false}}],"width":33.33333333333333,"minWidth":0,"height":50,"minHeight":0,"id":"bb_6744750","isClosable":true,"maximised":false,"activeItemIndex":0}],"width":50,"minWidth":50,"height":50,"minHeight":50,"id":"","isClosable":true},"openPopouts":[],"settings":{"constrainDragToContainer":true,"reorderEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"responsiveMode":"none","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10,"popInOnClose":false},"dimensions":{"borderWidth":5,"borderGrabWidth":5,"minItemHeight":10,"minItemWidth":10,"headerHeight":25,"dragProxyWidth":300,"dragProxyHeight":200},"header":{"show":"top","popout":"lock/unlock","dock":"dock","close":"close","maximise":"maximise","minimise":"minimise","tabDropdown":"additional tabs"},"resolved":true}
+"""";
+
+ string LayoutConfig3 = """"
+{"root":{"type":"stack","content":[{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_24636646","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签三","componentType":"component","componentState":{"id":"bb_24636646","showClose":true,"class":null,"key":"标签三","lock":false}},{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_60600063","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签一","componentType":"component","componentState":{"id":"bb_60600063","showClose":true,"class":null,"key":"标签一","lock":false}},{"type":"component","content":[],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_6744750","maximised":false,"isClosable":true,"reorderEnabled":true,"title":"标签二","componentType":"component","componentState":{"id":"bb_6744750","showClose":true,"class":null,"key":"标签二","lock":false}}],"width":50,"minWidth":0,"height":50,"minHeight":0,"id":"bb_60600063","isClosable":true,"maximised":false,"activeItemIndex":1},"openPopouts":[],"settings":{"constrainDragToContainer":true,"reorderEnabled":true,"popoutWholeStack":false,"blockedPopoutsThrowError":true,"closePopoutsOnUnload":true,"responsiveMode":"none","tabOverlapAllowance":0,"reorderOnTabMenuClick":true,"tabControlOffset":10,"popInOnClose":false},"dimensions":{"borderWidth":5,"borderGrabWidth":5,"minItemHeight":10,"minItemWidth":10,"headerHeight":25,"dragProxyWidth":300,"dragProxyHeight":200},"header":{"show":"top","popout":"lock/unlock","dock":"dock","close":"close","maximise":"maximise","minimise":"minimise","tabDropdown":"additional tabs"},"resolved":true}
+"""";
+}
diff --git a/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor.css b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor.css
new file mode 100644
index 00000000000..acc045f20f3
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLayout.razor.css
@@ -0,0 +1,14 @@
+.config {
+ display: block;
+ margin-top: 1rem;
+ border: 1px solid var(--bs-secondary);
+ border-radius: var(--bs-border-radius);
+ padding: 0.5rem;
+ overflow: auto;
+ height: 88px;
+}
+
+.dock-toggle-demo {
+ height: calc(100vh - 424px);
+ margin-top: 1rem;
+}
diff --git a/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLock.razor b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLock.razor
index 0eb0902e559..fa06e88977e 100644
--- a/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLock.razor
+++ b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewLock.razor
@@ -1,16 +1,16 @@
@page "/dock-view/lock"
@inherits BaseDockView
-锁定面板
+锁定面板
通过设置 DockView
的属性 IsLock
,控制所有面板是否能拖动
通过设置 DockComponent
的属性 IsLock
,控制某个面板是否能拖动
-
+
-
+
diff --git a/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewVisible.razor b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewVisible.razor
index 9263461a4cd..e94565949b0 100644
--- a/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewVisible.razor
+++ b/src/BootstrapBlazor.Shared/Samples/DockViews/DockViewVisible.razor
@@ -1,7 +1,7 @@
@page "/dock-view/visible"
@inherits BaseDockView
-可隐藏的面板
+可隐藏的面板
通过设置 DockComponent
的属性 Visible
控制面板的显示和隐藏
diff --git a/src/Extensions/Components/BootstrapBlazor.Dock/BootstrapBlazor.Dock.csproj b/src/Extensions/Components/BootstrapBlazor.Dock/BootstrapBlazor.Dock.csproj
index e1e89cf26ac..24688a2cc70 100644
--- a/src/Extensions/Components/BootstrapBlazor.Dock/BootstrapBlazor.Dock.csproj
+++ b/src/Extensions/Components/BootstrapBlazor.Dock/BootstrapBlazor.Dock.csproj
@@ -1,7 +1,7 @@
- 7.0.11
+ 7.0.12
diff --git a/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.cs b/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.cs
index 8de7a4bd6b9..5c4f074c31f 100644
--- a/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.cs
+++ b/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.cs
@@ -88,6 +88,12 @@ public partial class DockView
[Parameter]
public string? LocalStoragePrefix { get; set; }
+ ///
+ /// 获得/设置 布局配置
+ ///
+ [Parameter]
+ public string? LayoutConfig { get; set; }
+
private DockViewConfig Config { get; } = new();
private DockContent Content { get; } = new();
@@ -150,6 +156,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
EnableLocalStorage = EnableLocalStorage,
IsLock = IsLock,
Contents = Config.Contents,
+ LayoutConfig = LayoutConfig,
LocalStorageKeyPrefix = $"{LocalStoragePrefix}-{Name}",
VisibleChangedCallback = nameof(VisibleChangedCallbackAsync),
InitializedCallback = nameof(InitializedCallbackAsync),
@@ -203,11 +210,25 @@ public async Task Lock(bool @lock)
}
}
+ ///
+ /// 获取布局配置
+ ///
+ ///
+ public Task GetLayoutConfig() => InvokeAsync("getLayoutConfig", Id);
+
///
/// 重置为默认布局
///
///
- public Task Reset() => InvokeVoidAsync("reset", Id, GetOption(), Interop);
+ public Task Reset(string? layoutConfig = null)
+ {
+ var config = GetOption();
+ if (layoutConfig != null)
+ {
+ config.LayoutConfig = layoutConfig;
+ }
+ return InvokeVoidAsync("reset", Id, config);
+ }
///
/// 标签页关闭回调方法 由 JavaScript 调用
diff --git a/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.js b/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.js
index 9c938c052bd..1bbc3099590 100644
--- a/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.js
+++ b/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockView.razor.js
@@ -11,7 +11,7 @@ export async function init(id, option, invoke) {
await addLink("./_content/BootstrapBlazor.Dock/css/goldenlayout-bb.css")
const eventsData = new Map()
- const dock = { el, eventsData, lock: option.lock }
+ const dock = { el, eventsData, invoke, lock: option.lock, layoutConfig: option.layoutConfig }
Data.set(id, dock)
option.invokeVisibleChangedCallback = (title, visible) => {
@@ -74,7 +74,10 @@ export function update(id, option) {
const dock = Data.get(id)
if (dock) {
- if (dock.lock !== option.lock) {
+ if (dock.layoutConfig !== option.layoutConfig) {
+ reset(id, option)
+ }
+ else if (dock.lock !== option.lock) {
// 处理 Lock 逻辑
dock.lock = option.lock
lockDock(dock)
@@ -92,7 +95,17 @@ export function lock(id, lock) {
lockDock(dock)
}
-export function reset(id, option, invoke) {
+export function getLayoutConfig(id) {
+ let config = "";
+ const dock = Data.get(id)
+ if (dock) {
+ const layout = dock.layout
+ config = JSON.stringify(layout.saveLayout())
+ }
+ return config;
+}
+
+export function reset(id, option) {
const dock = Data.get(id)
if (dock) {
removeConfig(option);
@@ -108,7 +121,7 @@ export function reset(id, option, invoke) {
})
dispose(id)
- init(id, option, invoke)
+ init(id, option, dock.invoke)
}
}
@@ -122,6 +135,13 @@ export function dispose(id) {
dock.eventsData.clear()
dock.layout.destroy()
+
+ if (goldenLayout.bb_docks !== void 0) {
+ const index = goldenLayout.bb_docks.indexOf(dock);
+ if (index > 0) {
+ goldenLayout.bb_docks.splice(index, 1);
+ }
+ }
}
const lockDock = dock => {
@@ -291,21 +311,24 @@ const closeItem = (el, component) => {
}
const getConfig = option => {
- let config = null
option = {
enableLocalStorage: false,
+ layoutConfig: null,
name: 'default',
...option
}
- if (option.enableLocalStorage) {
- const localConfig = localStorage.getItem(getLocalStorageKey(option));
- if (localConfig) {
- // 当tab全部关闭时,没有root节点
- const configItem = JSON.parse(localConfig)
- if (configItem.root) {
- config = configItem
- resetComponentId(config, option)
- }
+
+ let config = null
+ let layoutConfig = option.layoutConfig;
+ if (layoutConfig === null && option.enableLocalStorage) {
+ layoutConfig = localStorage.getItem(getLocalStorageKey(option));
+ }
+ if (layoutConfig) {
+ // 当tab全部关闭时,没有root节点
+ const configItem = JSON.parse(layoutConfig)
+ if (configItem.root) {
+ config = configItem
+ resetComponentId(config, option)
}
}
@@ -474,7 +497,7 @@ const hackGoldenLayout = dock => {
this._closeButton.onClick = function (ev) {
// find own dock
- const dock = goldenLayout.bb_docks.find(i => i.layout === this.layoutManager);
+ const dock = goldenLayout.bb_docks.find(i => i.layout === this._header.layoutManager);
const eventsData = dock.eventsData
const tabs = this._header.tabs.map(tab => {
diff --git a/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockViewConfig.cs b/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockViewConfig.cs
index 9e4e99db65c..2619df29090 100644
--- a/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockViewConfig.cs
+++ b/src/Extensions/Components/BootstrapBlazor.Dock/Components/DockView/DockViewConfig.cs
@@ -67,4 +67,9 @@ class DockViewConfig
[JsonPropertyName("content")]
[JsonConverter(typeof(DockContentRootConverter))]
public List Contents { get; set; } = new();
+
+ ///
+ /// 获得/设置 布局配置 默认 null 未设置
+ ///
+ public string? LayoutConfig { get; set; }
}