提示:DockPanel Suite 的小改进,第一部分





5.00/5 (3投票s)
本提示展示了如何为使用 Weifen Luo 的 DockPanel Suite 的应用程序的“窗口”菜单添加对“新建水平选项卡组”和“新建垂直选项卡组”命令的支持,以及其他一些小的改进,以帮助确定至少有一个窗口是否停靠在主窗体的侧面。
引言
由 Weifen Luo 创建的 DockPanel UI 工具套件是创建模仿 Visual Studio 选项卡/停靠窗口环境的用户界面的一个优秀的开源解决方案。 我想为窗体菜单栏创建一个类似于 Visual Studio 环境中的“窗口”菜单。 因此,我决定从主DockPanel
类派生一个类,并将其命名为 StudioDockPanel
,然后将我的小改进放在这段代码中。 其中一项改进是实现 Visual Studio 环境的菜单栏上出现的“新建水平选项卡组”和“新建垂直选项卡组”命令。 这些命令允许你将一组选项卡“堆叠”在另一组的上方。代码
首先,我从 Weifen Luo 提供的DockPanel
类派生了一个类,名为 StudioDockPanel
namespace MyProject
{
public class StudioDockPanel : DockPanel
{
}
}
接下来,我添加了一个内部函数 NewHorizontalTabGroup
到其中internal void NewHorizontalTabGroup()
{
if (this.DocumentDockWindow == null
|| this.ActiveDocument == null)
return; // just no-op on error
IDockContent CurrentDocument = this.ActiveDocument;
DockPane CurrentPane = this.ActiveContent.DockHandler.Pane;
// create a new dock pane to the right of the current pane
// and then transfer the document to the new pane
DockPane NewPane = DockPaneFactory.CreateDockPane(CurrentDocument,
CurrentPane, DockAlignment.Bottom, 0.5, true);
NewPane.Show();
}
DocumentDockWindow
是我添加的一个属性,以便快速找到哪个 DockPanel.DockWinodws
包含选项卡式文档视图。public DockWindow DocumentDockWindow
{
get
{
foreach (DockWindow Window in DockWindows)
if (Window.DockState == DockState.Document)
return Window;
return null;
}
}
这非常简单明了;它只是搜索 DockWindows
列表并返回其 DockState
设置为 DockState.Document
的那个。 这是一个公共属性,因此你可以将其放入你当前的 代码中。 接下来,让我们看看如何添加一个新的垂直选项卡组。internal void NewVerticalTabGroup()
{
if (this.DocumentDockWindow == null
|| this.ActiveDocument == null)
return; // just no-op on error
IDockContent CurrentDocument = this.ActiveDocument;
DockPane CurrentPane = this.ActiveContent.DockHandler.Pane;
// create a new dock pane to the right of the current pane
// and then transfer the document to the new pane
DockPane NewPane = DockPaneFactory.CreateDockPane(CurrentDocument,
CurrentPane, DockAlignment.Right, 0.5, true);
NewPane.Show();
}
现在,当你有一个“窗口”菜单时,你希望更新菜单命令本身的 UI,以便除非打开了多个选项卡式文档,否则它们无法被选择。 否则,没有可用的内容可以添加到新的窗格中! 为此,我实现了一个 TwoOrMoreOpenDocumentWindows
属性public bool TwoOrMoreOpenDocumentWindows
{
get
{
if (this.DocumentDockWindow == null)
return false;
return this.DocumentDockWindow.VisibleNestedPanes[0].Contents.Count > 1;
}
}
IsDocumentVisible
属性告诉你是否根本存在活动文档。public bool IsDocumentVisible
{
get
{
return this.ActiveDocument != null;
}
}
最后,需要知道至少有一个窗格停靠在窗口侧面的要求。 这是为了更新用户界面并启用/禁用适当的菜单命令(浮动、停靠、作为选项卡式文档停靠、自动隐藏、隐藏等)。 因此,这有助于我们添加一个 IsAtLeastOnePaneDocked
属性public bool IsAtLeastOnePaneDocked
{
get {
foreach (DockWindow Window in DockWindows)
if (Window.DockState != DockState.Document
&& Window.VisibleNestedPanes.Count > 0)
return true;
return false;
}
}
就这样。 随着我对该库进行进一步的增强,以使其更接近这种类型环境的 UI 标准,将会出现更多的更新、提示或技巧。用法
要实现“窗口”菜单命令“浮动”、“停靠”、“作为选项卡式文档停靠”、“自动隐藏”和“隐藏”,我们执行以下操作(菜单命令的变量名应该不言自明)private void FloatWindow_Click(object sender, EventArgs e)
{
if (this.MainDockPanel.ActiveContent == null)
return;
this.MainDockPanel.ActiveContent.DockHandler.DockState = DockState.Float;
}
private void DockWindow_Click(object sender, EventArgs e)
{
if (this.MainDockPanel.ActiveContent == null)
return;
this.MainDockPanel.ActiveContent.DockHandler.DockTo(
this.MainDockPanel, DockStyle.Left);
}
private void DockWindowAsTabbedDocument_Click(object sender, EventArgs e)
{
if (this.MainDockPanel.ActiveContent == null)
return;
this.MainDockPanel.ActiveContent.DockHandler.DockState = DockState.Document;
}
private void AutoHideWindow_Click(object sender, EventArgs e)
{
if (this.MainDockPanel.ActiveContent == null)
return;
switch (this.MainDockPanel.ActiveContent.DockHandler.DockState)
{
case DockState.DockLeft:
this.MainDockPanel.ActiveContent.DockHandler.DockState = DockState.DockLeftAutoHide;
break;
case DockState.DockBottom:
this.MainDockPanel.ActiveContent.DockHandler.DockState = DockState.DockBottomAutoHide;
break;
case DockState.DockRight:
this.MainDockPanel.ActiveContent.DockHandler.DockState = DockState.DockRightAutoHide;
break;
case DockState.DockTop:
this.MainDockPanel.ActiveContent.DockHandler.DockState = DockState.DockTopAutoHide;
break;
default:
break;
}
}
private void HideWindow_Click(object sender, EventArgs e)
{
if (this.MainDockPanel.ActiveContent == null)
return;
this.MainDockPanel.ActiveContent.DockHandler.Hide();
}
private void AutoHideAll_Click(object sender, EventArgs e)
{
foreach (DockContent content in this.MainDockPanel.Contents)
{
switch (content.DockState)
{
case DockState.DockLeft:
case DockState.DockLeftAutoHide:
content.DockState = DockState.DockLeftAutoHide;
break;
case DockState.DockBottom:
case DockState.DockBottomAutoHide:
content.DockState = DockState.DockBottomAutoHide;
break;
case DockState.DockRight:
case DockState.DockRightAutoHide:
content.DockState = DockState.DockRightAutoHide;
break;
case DockState.DockTop:
case DockState.DockTopAutoHide:
content.DockState = DockState.DockTopAutoHide;
break;
default:
break;
}
}
}
private void NewHorizontalTabGroup_Click(object sender, EventArgs e)
{
this.MainDockPanel.NewHorizontalTabGroup();
}
private void NewVerticalTabGroup_Click(object sender, EventArgs e)
{
this.MainDockPanel.NewVerticalTabGroup();
}
private void ResetWindowLayout_Click(object sender, EventArgs e)
{
// TODO: Add code here to reset the window layout to the default
// Make sure to prompt the user to confirm
}
最后,你希望适当地更新“窗口”菜单命令// This is a handler for the DropDownOpening event of the Window menu
private void UpdateWindowMenu(object sender, EventArgs e)
{
int itemCount = windowMenu.DropDownItems.Count;
if (windowMenu.DropDownItems[itemCount - 1] is ToolStripSeparator)
windowMenu.DropDownItems.RemoveAt(itemCount - 1);
this.CloseAllDocuments.Enabled =
this.MdiChildren.Length > 0;
this.AutoHideAll.Visible = this.MainDockPanel.IsAtLeastOnePaneDocked;
this.NewHorizontalTabGroup.Visible = this.NewHorizontalTabGroup.Enabled = this.MainDockPanel.IsDocumentVisible
&& this.MainDockPanel.TwoOrMoreOpenDocumentWindows;
this.NewVerticalTabGroup.Visible = this.NewVerticalTabGroup.Enabled = this.MainDockPanel.IsDocumentVisible
&& this.MainDockPanel.TwoOrMoreOpenDocumentWindows;
if (this.MainDockPanel.ActiveContent == null)
{
this.FloatWindow.Enabled =
this.DockWindow.Enabled =
this.AutoHide.Enabled =
this.DockWindowTabbedDocument.Enabled =
this.HideWindow.Enabled = false;
return;
}
switch (this.MainDockPanel.ActiveContent.DockHandler.DockState)
{
case DockState.Document:
case DockState.Unknown:
this.FloatWindow.Enabled = true;
this.DockWindow.Enabled = true;
this.DockWindowTabbedDocument.Enabled = false;
this.AutoHide.Enabled = false;
this.HideWindow.Enabled = false;
break;
case DockState.DockBottom:
case DockState.DockBottomAutoHide:
case DockState.DockLeft:
case DockState.DockLeftAutoHide:
case DockState.DockRight:
case DockState.DockRightAutoHide:
case DockState.DockTop:
case DockState.DockTopAutoHide:
this.FloatWindow.Enabled = true;
this.DockWindow.Enabled = false;
this.DockWindowTabbedDocument.Enabled = true;
this.AutoHide.Enabled = true;
this.HideWindow.Enabled = true;
break;
case DockState.Float:
this.FloatWindow.Enabled = false;
this.DockWindow.Enabled = true;
this.DockWindowTabbedDocument.Enabled = true;
this.AutoHide.Enabled = false;
this.HideWindow.Enabled = true;
break;
default:
break;
}
}
就这样了。