扩展方法,使控件在复杂的层级结构中可见





0/5 (0投票)
在复杂的(或组合的)窗体中设置可见性。
此技巧是对以下技巧的补充:扩展方法,用于确定控件在复杂层级结构中是否可见[^].
考虑一下你拥有多个嵌套标签控件的情况
TabControlMain
TabPageMainOne
TabControlSubOne
TabPageSubOne
TabPageSubTwo
MyControl
TabPageMainTwo
TabControlMoreSubs
TabPageMoreSubsOne
TabPageMoreSubsTwo
使MyControl
在屏幕上可见的常见(朴素)方法既繁琐又容易出错
// Make my MyControl visible
TabControlSubOne.ActivePage = TabPageSubOne;
TabControlMain.ActivePage = TabPageMainOne;
这种方法在某种程度上有效,直到屏幕变成一个usercontrol
并放置在第三个TabControl
上。现在又多了一个需要考虑的控件,但你的代码并没有为此设计。这在动态组合的屏幕中是一种常见情况。
这种方法还有一个问题出现在屏幕内部,与可维护性有关。如果我们在重新设计屏幕并决定将MyControl
移动到TabPageMoreSubsTwo
会发生什么?现在代码实际上并没有显示该控件,但是,由于“断开”连接,我们可能直到后期才发现问题。
如前所述,这里的主要问题在于我们想要做的事情和我们实际做的事情之间的巨大差异。我们真正需要的是一个方法,它沿着父级层级结构一直到窗体,并“修复”所有TabControl
(或等效控件),以使控件可见。这就是此扩展的作用。
用法
// Make MyControl visible
MyControl.TabSwitchToControl();
此扩展方法的一个好处是,我们抽象了“如何”,只保留了源代码的“什么”。可读性 +1。
public static void LogError(this Exception ex)
{
//TODO: use your prefered error logging mechanism
}
/// <summary>
/// Tries to make your control visible by setting the
/// 'active tab' property (or equivalent) of all tabcontrols
/// (or other container controls) in your form hierarchy.
/// The method does this in the same order as a user would have to, when using the interface.
/// Supports: TabControl, UltraTabPageControl, UltraExplorerBarContainerControl.
/// </summary>
/// <param name="subjec">The subject.<</param>
/// <param name="shouldActivateControl">True if the control should be activated/selected.</param>
/// <returns>true if subject is assigned, otherwise false.</returns>
public static bool TabSwitchToControl(this Control subject, bool shouldActivateControl = false)
{
bool result = true;
if (subject == null)
{
result = false;
}
else
{
List<control> tabSwitches = new List<control>();
#region Build a list of tabswitched to perform to make the control visible
var testSubject = subject;
while (testSubject != null)
{
var asTabPage = (testSubject as TabPage);
if (asTabPage != null)
{
var asTabControl = asTabPage.Parent as TabControl;
if (asTabControl != null)
{
tabSwitches.Insert(0, testSubject);
testSubject = asTabControl;
}
}
else
{
var asUltraPage = testSubject as UltraTabPageControl;
if (asUltraPage != null)
{
tabSwitches.Insert(0, testSubject);
testSubject = asUltraPage.TabControl;
}
else
{
var asGroupContainer = testSubject as UltraExplorerBarContainerControl;
if (asGroupContainer != null)
{
tabSwitches.Insert(0, testSubject);
testSubject = asGroupContainer.Parent;
}
}
}
// jump up one parent in the hierarchy until the top control is reached.
if (testSubject != null)
{
testSubject = testSubject.Parent;
}
}
#endregion
//apply the tabswitches in the same order as a user would.
foreach (Control control in tabSwitches)
{
try
{
var page = control as UltraTabPageControl;
if (page != null)
{
page.TabControl.SelectedTab = page.Tab;
}
else
{
var asTabPage = control as TabPage;
if (asTabPage != null)
{
var tabControl = asTabPage.Parent as TabControl;
tabControl.SelectedTab = asTabPage;
}
else
{
var asExplorerContainer = control as UltraExplorerBarContainerControl;
if (asExplorerContainer != null)
{
var explorerBar = (control.Parent as UltraExplorerBar);
var explorerGroup = explorerBar.Groups[control.Name];
if (explorerBar.SelectedGroup != explorerGroup)
{
explorerBar.SelectedGroup = explorerGroup;
}
}
}
}
}
catch (Exception exp)
{
// Catch exceptions to prevent application termination because of
// a bad event handler. For example a refresh of a control failed
// because the internet connection was dropped.
exp.LogError();
result = false;
}
}
if (shouldActivateControl)
{
subject.Select();
}
}
return result;
}
(编辑:修复了一些错别字)