我的应用程序具有以下UI配置:
主窗体是MDI容器。其子表单附加到TabStrip
。
每个用户都有他的一组子表单。根据活动用户的不同,仅显示该用户的子表单以及选项卡。
这是通过浏览主窗体的MdiChildren
并将其Visible
属性设置为false/true
来实现的,具体取决于活动用户。
foreach (Form item in MdiChildren)
{
if (((OfficeFormEx)item).UserID == (int)e.NewTab.Tag)
{
item.Visible = true;
}
else
{
item.Visible = false;
}
}
这有两个不良影响。一个是每个儿童形式连续重绘,这是丑陋和缓慢的。另一个是由于某种原因,形式从最大化到正常,有效地将它们从主要形式脱离。
有没有办法只显示其中一个子表单,例如用户之前正在查看的表单,并让其他表单保留在后台?最大化/正常的事情并不是那么大,因为我可以手动再次最大化它们。
答案 0 :(得分:2)
乍一看,我会看一下Form.WindowsState
属性,如果你还没有。我怀疑如果您碰巧在设计时将此属性设置为FormWindowState.Maximized
,则在设置Visible
属性true
/ false
时会更改此属性。
对于“[...]每个子表单连续重绘[...]” - 事情,您是否尝试在活动用户表单验证的开头使用SuspendLayout()
方法,并且之后调用ResumeLayout()
?
编辑#1
Form
。这样做会减少应用程序使用的内存量,而且会大大减少
MdiChildren
集合属性中包含的表单数量。然后,如果仍然需要,迭代整个集合将会更快。
如果这不是您的选择,那么使用 Linq 可能有所帮助:
var visibleForms = from f in MdiChildren
where (((OfficeFormEx)f).UserID == (int)e.NewTab.Tag)
select f;
var invisibleForms = from f in MdiChildren
where (((OfficeFormEx)f).UserID != (int)e.NewTab.Tag)
select f
visibleForms.ToList().ForEach(f => f.Visible = true);
invisibleForms.ToList().ForEach(f => f.Visible = false);
如果您使用的是.NET 4.0,那么这可能是PLINQ
的理想候选人
请提供反馈,以便我们能够找到解决方案。 =)
答案 1 :(得分:2)
如果没有代码段,您的问题就不是很清楚了。但是,您正在与Windows MDI实施进行斗争。它不支持的一件事是隐藏一个子窗口,它只能最小化。 Windows窗体通过销毁Window句柄来实现Visible属性,当Visible属性再次设置为True时重新创建它。窗口的新实例将不会最大化。
当当前窗口最大化时,它也不支持将焦点切换到子窗口。 WF的解决方法是强制活动子窗口恢复到正常状态。
MDI模型不太适合在最大化状态下显示子窗口。要获取选项卡式界面,请使用TabControl并在其选项卡页面上显示UserControl。
答案 2 :(得分:1)
我最终解决了这个,所以这是一个迟来的写作。
Marcouiller会建议SuspendLayout()
和ResumeLayout()
,但这些都不起作用。这使我开始研究这两种方法实际上做了什么,并得出结论,我需要的是在MDI儿童的操作正在进行时停止主要形式重绘的方法。
这反过来导致以下两个静态实用程序方法暂停重绘给定控件。在我的情况下,暂停重绘主表格会导致大幅加速。
/// <summary>
/// suspends drawing on a control and its children
/// </summary>
/// <param name="parent"></param>
public static void SuspendDrawing(Control control)
{
SendMessage(control.Handle, WM_SETREDRAW, false, 0);
}
/// <summary>
/// resumes drawing on a control and its children
/// </summary>
/// <param name="parent"></param>
public static void ResumeDrawing(Control control)
{
SendMessage(control.Handle, WM_SETREDRAW, true, 0);
control.Refresh();
}