Focus to the right control when entering the next page

Wizard for Windows Forms Forum

Posted 9 years ago by Chavadam - Belgium
Version: 3.0.0143

Here is my question regarding 'Actipro for Windows Form' more than .Net, Windows Form or C# :

All the 'interior pages' of my wizard feature a 'SplitContainer' containing a 'TreeView' in the 'Panel1' and a 'DataGridView' in the 'Panel2'.
I need to have that at each transition to the next page, the focus is always given to the 'DataGridView'. That means that :
- this control receives the keyboard actions (Arrow up, arrow down) directly
- whithout the user having first to click on the DataGridView
- that this focus should be given at entering og the int. page.
Preferably by putting in the constructor a statement particular to the DataGridView (not to the SplitContainer.Panelx)

In my classes layout,
doesn't make it.

In my 'WizardForm' main form (partial class with 'WizardForm.designer'), I have (as it has to be):
        private void WizardNextButton(object sender, ActiproSoftware.Wizard.WizardPageCancelEventArgs e)
            switch (Wizard.SelectedIndex)
                case (int)WizPagType.wizPag0:    // Welcome page
                case (int)WizPagType.wizPag1:
                    // Getting the focus without having first to click on the DataGridView control.
                    wizPag1_TreeAndGrid.dataGridView.Focus();   // Doesn't work.
                case (int)WizPagType.wizPag2:
Having a '...dataGridView.Focus()' statement linked to the Next button activation when we still are in the previous interior page can't help to determine the control getting the focus in the 'arriving' page.
Could other events help me that the event particular to the 'Next' button activation ? An event like 'AtPageEntering' ?
- Selection Changed event ?
- GotFocus event

Remark 1 : Not at the 'constructors' execution time, which occurs a long time before.
Remark 2 : I organized my classes such a way that I have one class (of TreeView and DataGridView) for each interior page.

I think it is a question that could impact a lot of developers using Actipro, isn't it ?
Many thanks in advance.

[Modified at 07/05/2010 10:08 AM]

Comments (6)

Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Hi Charles,

What if you set the focus in the Wizard.SelectionChanged event?

Actipro Software Support

Posted 9 years ago by Chavadam - Belgium
Hello Administrator / Support,

I was just implementing a new EventHandler to react on the 'SelectionChanged' event :

    class EventListener
        public EventListener(Wizard sMConfig_WizContr)
            this.wizard = sMConfig_WizContr;
            // Add "intPageChanged" to the 'SelectionChanged' event on "wizard".
            this.wizard.SelectionChanged += new EventHandler(intPageChanged);

        // This will be called whenever the wizard page changes.
        private void intPageChanged(object sender, EventArgs e)
            int i;
            Control ctrl = new Control();
            for (i=0 ; i < this.wizard.SelectedPage.Controls.Count ; i++)
                ctrl = this.wizard.SelectedPage.Controls[i];

                // Looking for 'i' corresponding to the unique 'DataGridView' in each int. page
                // if (this.wizard.SelectedPage.Controls[1].GetType() == typeof(DataGridView))
/*                if (ctrl.GetType() == typeof(Frames_DataGridV))
                // MessageBox.Show(ctrl.ToString());    // f.i. "frames_TreeAndGrid"
            // this.wizard.SelectedPage.Controls[i].Focus();

        public void Detach()
        {   // Detach the event and delete the wizard
            this.wizard.SelectionChanged -= new EventHandler(intPageChanged);
            this.wizard = null;

        private Wizard wizard;
but I encounter problems now with the fact that
ctrl = this.wizard.SelectedPage.Controls[i];
returns me the list of Controls own to each wizard page (3 for the Welcome page; 1 for each 'interior page' ...).
What I'm look for is the right statement to get the list of Controls inside each of these wizard pages, for instance:
TreeView, SplitContainer, BorderLayoutPane, DataGridView, Panel (of buttons), Buttons, ...
Above all my DataGridView (embedded in a BorderLayout, itself embedded in a Pane, ...). I think to a re-entrant function. But which is the right syntax to fing the Controls embedded in a parent Control, itself embedded in a grand-parent Control ?
this.wizard.SelectedPage.Controls. ??? 
As you see, this is still a concrete and usual situation, and an interesting issue for much Actipro wizard users, I think.
Thanks for your feedback

[Modified at 07/06/2010 10:33 AM]
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Hi Charles,

The Controls collection is generic. You basically have two options...

1) You could write a recursive method to go through the Controls collection and return the first DataGridView you find. Then focus that in the SelectionChanged event handler.

2) You could maybe attach to each page's GotFocus event and forward focus to the appropriate child control.

However note that when we run our sample, the first control on each page is getting focus properly. So I would think your grid would also get focus properly as long as it was the first control in the tab order within each page, without having to do either of the options above.

Actipro Software Support

Posted 9 years ago by Chavadam - Belgium
My first issue is that
always return '1' for every inter. page.

Every of my inter. pages feature the same layout:
Level 1 : A 'SplitContainer' only (hence the '1' for Count, probably)
Level 2-1 : A 'TreeView' in the 'Panel1'
Level 2-2 : A 'BorderLayout' in the 'Panel2'
Level 2-2-1 : A 'DataGridView' in the 'Center' part of this 'BorderLayout' - On which I want the focus when entering the inter. page.
Level 2-2-2 : A button panel in the 'South' part of this 'BorderLayout'

Every of the SplitContaner, TreeView, DataGrid, Button Panel has a different TabIndex nr. DataGridView.TabIndex is '2' for every inter. pages.

The first part of my question was : Which methods, properties of Actipro can I use to reach deeper Controls than the unique Control of 'Level 1'.
Of course, with
, I get the error "Out of range...".

Something like
where the indexes correspond to the programmed TabIndexes.

Only when this point is solved, I could think to 'datagridview.Focus()'.

[Modified at 07/07/2010 06:37 AM]
Posted 9 years ago by Chavadam - Belgium
And the answer is ...

            if (this.wizard.SelectedPage.IsInteriorPage == true)
            {   // Every inter. page contains a 'DataGridView' whose TabIndex = 2.
                /* Shows the nr of controls in the Nth level of each inter. page.
                 * MessageBox.Show(this.wizard.SelectedPage.Controls.Count.ToString()); Always 1 (= 'SplitContainer')
                 * MessageBox.Show(this.wizard.SelectedPage.Controls[0].Controls.Count.ToString()); 2 (= 'ControlCollection')
                 * MessageBox.Show(this.wizard.SelectedPage.Controls[0].Controls[1].Controls.Count.ToString()); 2
                // Controls[0].Controls[1].Controls[1] --> 'particular_DataGridView'
                if ((ctrl = this.wizard.SelectedPage.Controls[0].Controls[1].Controls[1]) is DataGridView)
I let you find the correspondence between the index value of each control and the explanation of the levels in my previous message ...
Posted 9 years ago by Actipro Software Support - Cleveland, OH, USA
Hi Charles,

The Controls collection is something defined by WinForms itself, and we don't really have anything to do with it. It provides a generic hierarchy to navigate through the WinForms controls that are present.

If your page has one child control on it, then yes, "this.wizard.SelectedPage.Controls[2]" will certainly blow up since 2 is out of range. It can't be larger than 0 in that case.

As you showed in your second code snippet, that is one way to get to your grid. However that assumes that your control hierarchy is always exactly the same in each page. If that remains true, then it will work. However a better design is the one I mentioned where you write a recursive method that takes a controls collection, scans it for a DataGrid, returns it if found, but if not will recurse into each child control's Controls collection to look for it. That way you don't care about specific indices in case your control hierarchy changes in the future.

Actipro Software Support

The latest build of this product (v2018.1 build 0341) was released 3 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.