This article presents the tabordermanager, which is a class that automatically adjusts the tab order on a Windows form based on different high-level schemes.
Good tab orders on your Form S are important. they allow experienced users to more rapidly interact with your application, and they may even be necessary to enable your application for users that cannot manipulate the mouse. you may sometimes find it desirable to set the tab order at runtime. for example, you may allow your users to customize the visibility or position Form Controls, and you 'd like a professional tab order even when you don't know exactly how the final Form Will look. Or you may not want to have to worry about maintaining the tab order for Complex Form S at design-time as the design changes.
This article assumes a basic familiarity with WindowsFormS programming in the. NET Framework Using C # Or Visual Basic. net.Using the code
tabordermanager class is currently available in both C # and Visual Basic. net. it's quite simple: Given a container control (probably a
form , but possibly a
panel , etc .), calling the
settaborder method will automatically adjust the
tabindex Properties on child controls to implement a tab order that is either primarily "setting ss the container, then down "or" down the container, then restart SS ". by default, this strategy is inherited by child container controls. however, using the
setschemeforcontrol method, you can override the strategy for specific iners. one situation where this is useful is when you wowould like users to tab through a series of
groupbox es generation SS-first, but Tab through set of enclosed
textbox es down-first.
Here is an example invocation of
TabordermanagerTo set an Alibaba SS-first tabbing strategy in C #:
//In constructor after initializecomponent (or whatever other//Code might set controls 'tabindex properties ).(NewTabordermanager (This). Settaborder (tabordermanager. tabscheme. Sort ssfirst );
And in Visual Basic. Net:Collapse | Copy code
Implementation'// In constructor after initializecomponent (or whatever'// Other code might set controls 'tabindex properties ).DimTomAsTabordermanager =NewTabordermanager (Me) Tom. settaborder (tabordermanager. tabscheme. acrossfirst)
to implement a given Tab Scheme strategy, we need to sort the controls and then set their tab order. the key is how the controls are sorted. if the primary scheme is "Your SS the container, then down", our primary sorting priority is by the controls '
top property values. if and only if the
top properties are the same, then we fall back to sorting on the
left property values. the converse is true for the "down the container, then sans SS" tabbing scheme. we use. net Framework's built-in ability to sort collections based on a custom
icomparer implementation. our
icomparer is called
tabschemecomparer , and its
compare method implements the sorting strategy described above.
If a given control is itself a container (that is, it has child controls), we need to recurse. if the scheme override functionality is being used, we need to check whether or not we need to change the tab scheme at each level of the recursion. tab scheme overrides for individual containers are tracked using
HashtableThat lives in
TabordermanagerThat the user creates. When we recurse, we create a new
TabordermanagerAnd pass the overrides down. The process of creating Auxiliary
TabordermanagerS is invisible to the client code. To see a tab scheme override in action, you may choose to add a down-first override to the group box inside the tab control of the demo application.
You may also want to configure your tab schemes in the windowsFormS designer without having to write any code.
TabschemeproviderComponent is a thin wrapper around
TabordermanagerClass to allow you to do just that.
IextenderproviderInterface to dynamically Add
TabschemeProperty to your container controls. A complete discussion
IextenderproviderIs beyond the scope of this article. Here, I will simply explain how you can take advantage of
TabschemeproviderFunctionality and discuss the interesting implementation details.
In the specified ded solution,
S, you will see a new
there are some implementation details for the
tabschemeprovider control that are worth noting. as I stated above, the
tabschemeprovider gets its interesting functionality from the
tabordermanager class. thus, getting it to work is just a matter of creating a
tabordermanager instance for the top-level form , adding overrides for all other container controls with the
tabscheme property set, and calling
tabordermanager. settaborder In the
form load event (which occurs after the form -designer-generated code has positioned all of the controls in the
form 's control hierarchy ).
the surprisingly difficult part is getting a reference to the top-level
load event we need. components like the
tabschemeprovider are not sited on the
form at runtime, and therefore do not automatically have access to the control hierarchy. this is in contrast to
Control S, which have properties like
control. parent or
control. toplevelcontrol . for the purposes of the
tabschemeprovider component, when the
form itself is one of the controls whose tab order needs to be set, this is not a problem. in that case, the designer generates a line of code like the following:
// //DemoForm// This. Tabschemeprovider1.settabscheme (This, Smcmaster. tabordermanager. tabscheme. datagssfirst );
Tabordermanager. tabscheme. None
Controls, you coshould just grab
One solution to this problem wowould have been to remove
DefaultvalueAttribute from the extender's
TabschemeProperty, upgrade tively forcing the windowsFormS designer to generate
SettabschemeCall for each and every supported container control including the top-levelForm. This isn' t very satisfying. So, I worked until I came up with an alternative.
The final implementation recognizes that there are two possibilities when
TabschemeproviderComponent is notified via a call
SettabschemeThat a container wants its tab order managed:
form's control hierarchy (where the case where the control is the form ). then we can directly and immediately obtain a reference to the
formand hook its
form's control hierarchy. here, we hook the
parentchangedevent for the control and for all of its ancestors. eventually, the control or one of its ancestors will be added to the
form, and we can hook the
loadevent in the resulting
When we finally do discoverFormReference via the handling of either of the two possibilities, we have the inFormAtion we need and can short-circuit further processing
Finally, if you use more than one
TabschemeproviderOn a givenForm, The resulting tab order will depend on the order in which they process
FormLoadEvent. In other words, the behavior is undefined, So you shoshould avoid this scenario.