我在我的WinForms桌面应用程序中使用 Microsoft 的SplitContainer控件。
我想在拆分器控件的面板之间有一个小按钮(或任何漂亮的 UI 元素)来折叠其中一个面板。例如,一个有两个部分的“按钮”,如果我单击一个部分,右侧面板会折叠,如果我单击另一部分,左侧面板会折叠。
这可能吗?这怎么可能实施?
我在我的WinForms桌面应用程序中使用 Microsoft 的SplitContainer控件。
我想在拆分器控件的面板之间有一个小按钮(或任何漂亮的 UI 元素)来折叠其中一个面板。例如,一个有两个部分的“按钮”,如果我单击一个部分,右侧面板会折叠,如果我单击另一部分,左侧面板会折叠。
这可能吗?这怎么可能实施?
我在我的实现中使用了这个解决方案,对你来说可能为时已晚,但可能会帮助其他人。
在我的实现中,我还将控件从一个面板移动到另一个面板,这就是为什么我只将面板折叠状态更改为最后一个操作。
由于我无法发布任何图像,请尝试根据下图弄清楚([<]和[>]是按钮):
╔════════════╤═════════════╗
║ [<]│[>] ║
║ │ ║
║ │ ║
║ │ ║
║ │ ║
║ │ ║
╚════════════╧═════════════╝
以下是左侧面板(panel1)的实现,右侧面板也使用了类似的功能。
private void setSplitterLeftPanelCollapsedState(bool collapse)
{
splitContainer1.SuspendLayout();
// Collapse the left panel
if (collapse)
{
if (!splitContainer1.Panel1Collapsed)
{
// restoring the panel in the end to apply layout changes
buttonOpenPanel1.Text = ">";
splitContainer1.Panel1Collapsed = true;
}
}
// Open the left panel
else
{
if (splitContainer1.Panel1Collapsed)
{
// collapsing the panel in the end to apply layout changes
buttonOpenPanel1.Text = "<";
splitContainer1.Panel1Collapsed = false;
}
}
splitContainer1.ResumeLayout();
comboBoxSearchText.Focus();
}
受 Lotus Notes 布局的启发,我设计了一些我认为在这种情况下有用的东西。它仅包含面板之间的一个按钮,用于切换单个面板的展开/折叠状态,但可以轻松修改为使用两个按钮来控制左右面板。它使用两个拆分容器,一个停靠在另一个内部,并使用“中间”面板的 mouseMove 事件来模拟拖动拆分器(在 C# 中通过用鼠标拖动控件来移动控件)。此外,我使用容器的 ClientSizedChanged 事件来处理切换按钮图像的逻辑,而不是折叠/展开面板的方法(检测 SplitContainer 折叠时发生的变化)。
设计:
splitContainer1
╔════════════╤═════════════════════════════════╗
║ │ splitContainer2 (docked fill) ║
║ │ ╔════════════╤════════════════╗ ║
║ │ ║ │ ║ ║
║ │ ║ Button(s) │ ║ ║
║ │ ║ [<>] │ ║ ║
║ │ ║ │ ║ ║
║ │ ╚════════════╧════════════════╝ ║
╚════════════╧═════════════════════════════════╝
splitContainer2.Dock = DockStyle.Fill;
splitContainer1 = splitContainer2.IsSplitterFixed = true;
splitContainer2.Panel1.Cursor = Cursors.VSplit;
向左或向右锚定按钮(或将多个按钮停靠在 tableLayout 控件内)。只要确保面板的某些部分仍然可以单击/拖动即可。
将中间面板的最大值设置为较低的数字。大小取决于您需要按钮的宽度。
代码:
面板将切换到相反状态
如果您真的需要一个带有两个部分的按钮而不是两个按钮或一个切换按钮,您将需要单击鼠标坐标并根据单击发生的位置具有不同的逻辑。
private void btnExpand_Click(object sender, EventArgs e)
{
splitContainer1.Panel1Collapsed = !splitContainer1.Panel1Collapsed;
}
与展开/折叠相关的处理逻辑。我选择使用这个事件是因为在我的程序中有几种方法可以让用户折叠/展开面板。
private void splitContainer1_Panel2_ClientSizeChanged(object sender, EventArgs e)
{
if (splitContainer1.Panel1Collapsed)
{
splitContainer2.Panel1.Cursor = Cursors.Default;
this.btnExpand.Image = imageExpand;
}
Else
{
splitContainer2.Panel1.Cursor = Cursors.VSplit;
this.btnExpand.Image = imageCollapse;
}
}
处理由于移动人造分离器而调整面板的大小
private void splitContainer2_Panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
/* All you really need is this:
splitContainer1.SplitterDistance += e.X;
Note: Splitter distance must be a positive integer and e.X will be negitive when dragging to the left of the splitContainer. You could handel this check here or on the splitterMoving event.
The code I have below shows how to “snap” a panel closed if the splitter is moved close enough to the edge
Or prevent a panel from being hidden from view (which could also be accomplished by setting the minimum size of a panel).
*/
if (e.X + splitContainer1.SplitterDistance < 40)
{
while (splitContainer1.SplitterDistance > 1)
splitContainer1.SplitterDistance--;
splitContainer1.Panel1Collapsed = true;
}
else if ((e.X + splitContainer1.SplitterDistance) * 1.00 / this.Width * 1.00 < .75)
splitContainer1.SplitterDistance += e.X;
else
Cursor.Current = Cursors.No;
}
}