C# -- "CurrentCell" FOCUS ?

finance_teacher
finance_teacher used Ask the Experts™
on
How can I change the below "BatchError"
so it puts focus back on STOCKNUM cell
since "Cells[0]" fails ?

        private void BatchError(int vRowNumber, int vColumnNumber)
        {
            try
            {
                    string vStockNumber = this.gML_ROITEMDataGridView.Rows[vRowNumber].Cells[vColumnNumber].Value.ToString();
                    DataRow[] nDR = this.gmL_ITEMMSTRTableAdapter1.GetDataBy_vStockNumber(vStockNumber).Select();
                    if (nDR.Length <= 0)
                    {
                        MessageBox.Show("Stock Number not found");
                        this.gML_ROITEMDataGridView.Rows[vRowNumber].Cells[vColumnNumber + 1].Value = "";
                        this.gML_ROITEMDataGridView.CurrentCell = gML_ROITEMDataGridView.CurrentRow.Cells[0];
                    }

I am also willing to use the
"CellValidating" EVENT and
setting "e.cancel" to true
if the above is not possible.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Craig WagnerSoftware Architect

Commented:
Do this...

gML_ROITEMDataGridView.CurrentCell = gML_ROITEMDataGridView[0, vRowNumber];

Author

Commented:
I tested three diffferent ways (below) on my dotNet 2.0 APP and they displayed the below "test1" as "DataGridViewTextBoxCell { ColumnIndex=0, RowIndex=0 }" which means FOCUS should have moved back to the STOCKNUM cell, however FOCUS continues to display in the DESCRIPTION cell (attached)

How can I fix ?

       = gML_ROITEMDataGridView.CurrentRow.Cells[1]
        = gML_ROITEMDataGridView[0, this.gML_ROITEMDataGridView.CurrentRow.Index];
        = gML_ROITEMDataGridView[0, vRowNumber];
---------------------------------------------------------------------------------------
string test1 = gML_ROITEMDataGridView.CurrentCell.ToString();
0001.jpg
Craig WagnerSoftware Architect

Commented:
There must be something else going on. I created a new form, threw a datagridview on it, populated it with rows, set the current cell, and I get the identified cell as current. Here's the code I used. When I run it the messagebox displays "DataGridViewTextBoxCell { ColumnIndex=3, RowIndex=2 }." I've also included a screenshot of the running form.

Do you maybe have an event handler for another event on the dgv that is causing currentcell to change again after you've set it?
private void Form1_Load( object sender, EventArgs e )
{
    dataGridView1.Rows.Add( "a", "b", "c", "d", "e" );
    dataGridView1.Rows.Add( "a", "b", "c", "d", "e" );
    dataGridView1.Rows.Add( "a", "b", "c", "d", "e" );
    dataGridView1.Rows.Add( "a", "b", "c", "d", "e" );

    dataGridView1.CurrentCell = dataGridView1[3, 2];

    string test1 = dataGridView1.CurrentCell.ToString();

    MessageBox.Show( test1 );
}

Open in new window

ScreenShot.png
Expert Spotlight: Joe Anderson (DatabaseMX)

We’ve posted a new Expert Spotlight!  Joe Anderson (DatabaseMX) has been on Experts Exchange since 2006. Learn more about this database architect, guitar aficionado, and Microsoft MVP.

Author

Commented:
Doing the below #1 works fine,
but doing the below #2 fails, redisplaying
"Stock Number not found" again and again,
without letting the user correct their error.

How can I fix ?
---------------------------------------------------------------------------------------
#1

        private void gML_ROITEMBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.gML_ROITEMBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.dataSet1);
            gML_ROITEMDataGridView.CurrentCell = gML_ROITEMDataGridView[5, 0];
        }
---------------------------------------------------------------------------------------
#2

        private void gML_ROITEMDataGridView_CellValidated(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_ROITEMDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "STOCKNUM")
            {
                string vStockNumber = this.gML_ROITEMDataGridView.Rows[vRowNumber].Cells[vColumnNumber].Value.ToString();
                DataRow[] nDR = this.gmL_ITEMMSTRTableAdapter1.GetDataBy_vStockNumber(vStockNumber).Select();
                if (nDR.Length <= 0)
                {
                    MessageBox.Show("Stock Number not found");
                    gML_ROITEMDataGridView.CurrentCell = this.gML_ROITEMDataGridView[0, 0];
                }
            }
        }

Commented:
You failed to add e.Cancel = True after you show your MessageBox.  If you add that, you should NOT need to set the CurrentCell.

Jake

Commented:
Oops, of course it's e.Cancel = True; (Forgot the semicolon =P)

Jake

Author

Commented:
Ok, I will retest.

Author

Commented:
Doing the below with
e.Cancel = true; still fails, redisplaying
"Stock Number not found" again and again,
without letting the user correct their error.

How can I fix ?
------------------------------------------------------------
        private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    MessageBox.Show("Stock Number not found");
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                    e.Cancel = true;
                }
            }
        }

Author

Commented:
Doing the below with
e.Cancel = true; still fails, redisplaying
"Stock Number not found" again and again,
without letting the user correct their error.

How can I fix ?
------------------------------------------------------------
        private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    MessageBox.Show("Stock Number not found");
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                    e.Cancel = true;
                }
            }
        }

Commented:
finance_teacher,

Your creating an endless loop...

Your trying to move the cell:

gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];

And yet rejecting the Validation, which brings focus back, which causes validation, repeat...

Jake

Author

Commented:
How can I change the below to work ?
--------------------------------------------------------
        private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    MessageBox.Show("Stock Number not found");
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                    e.Cancel = true;
                }
            }
        }

Commented:
Remove the e.Cancel, since you've essentially handled it already (I assume).
private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    MessageBox.Show("Stock Number not found");
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
            }
        }

Open in new window

Author

Commented:
Still fails, redisplaying
"Stock Number not found" again and again,
without letting the user correct their error.

Originally I did not have "e.Cancel", then I added, then I removed.

How can I fix ?
Craig WagnerSoftware Architect

Commented:
The problem is this line of code:

gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];

The CellValidating event fires whenever the current cell focus is changing. By programatically changing the current cell you're causing the CellValidating event to fire again and getting stuck in a loop.

Typically this is what you want. The purpose of the CellValidating event is to validate the contents of the current cell, so you would want to leave focus in that cell to allow the user to correct the problem with the value in that cell.

Even if you could find a way around it, the DataGridView would just allow focus to go to the next cell anyway.

I think you need to take a step back from trying to get the existing code to work and reconsider what the purpose of the design really is. It seems to me you're using the wrong event to accomplish what you're trying to accomplish, but it's hard to tell what the fundamental requirement is that you're trying to address by just looking at non-working code.

Author

Commented:
Details Below.
 1. I have a datagrid view
 2. user enters a stockNumber into datagrid
 3. clicks TAB
 4. below runs and populates datagrid's description column if stockNumber is valid
 5.  if stockNumber is NOT valid below displays "Stock Number not found" and should
     put FOCUS back into stockNumber column so user can enter a new stockNumber

How can I get above #5 to work ?
-----------------------------------------------------------------------------------------------------------
        private void BatchError(int vRowNumber, int vColumnNumber)
        {
            try
            {
                    string vStockNumber = this.gML_ROITEMDataGridView.Rows[vRowNumber].Cells[vColumnNumber].Value.ToString();
                    DataRow[] nDR = this.gmL_ITEMMSTRTableAdapter1.GetDataBy_vStockNumber(vStockNumber).Select();
                    if (nDR.Length <= 0)
                    {
                        MessageBox.Show("Stock Number not found");
                        this.gML_ROITEMDataGridView.Rows[vRowNumber].Cells[vColumnNumber + 1].Value = "";
                        this.gML_ROITEMDataGridView.CurrentCell = gML_ROITEMDataGridView.CurrentRow.Cells[0];
                    }

Commented:
finance_teacher,

By calling e.Cancel = True, the cell remains focused.

Jake

Author

Commented:
I also tried the below and it still LOOPS forever.

How can I get it to not LOOP ?
----------------------------------------------------------
        private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    Testing();
                }
            }
        }
----------------------------------------------------------
        private void Testing()
        {
            gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
        }

Commented:
finance_teacher,

Check out the code below...  As I said, simply reinstate e.Cancel = True;, and remove your CurrentCell call...

Jake
private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    // Do your test
                    e.Cancel = True; //<- Prevents cell from losing focus.
                }
            }
        }

Open in new window

Craig WagnerSoftware Architect

Commented:
Your CellValidating event handler will do exactly what you listed, just remove the line of code that tries to set the current cell. The cell you are validating is the cell you want to retain focus.
private void dataGridView1_CellValidating( object sender, DataGridViewCellValidatingEventArgs e )
{
    int vRowNumber = e.RowIndex;
    int vColumnNumber = e.ColumnIndex;
    string vColumnName = dataGridView1.Columns[e.ColumnIndex].DataPropertyName;

    if( vColumnName.ToLower() == "stocknumber" )
    {
        // Look up stock number
        if( stockNumber is not found )
        {
            MessageBox.Show( "Stock Number not found" );
            e.Cancel = true;
        }
        else
        {
            // set the description column 
        }
    }
}

Open in new window

Author

Commented:
How can I get the below to set
"CurrentCell" FOCUS on column 3,3 ?
------------------------------------------------------------------------------------
private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                if (1 != 1) // stockNumber not found
                {
                      MessageBox.Show( "Stock Number not found" );
                    e.Cancel = true;
                }
                else
                {
                      gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
            }
        }

Commented:
finance_teacher,

I'm not sure WHY you want to do that (Set focus to a specific row and column; I assume they it is guaranteed to ALWAYS exist?)...  However, because you are doing this in your validation code, unless you e.Cancel, .NET will try and give focus to the next cell, or the cell you clicked on to cause the validation.  I suspect that focus is quickly given to this.gML_BRANDDataGridView[3, 3], then shifted to either the next cell or the clicked on cell by the runtime.

Perhaps you could add this additional logic in gML_BRANDDataGridView_CellLeave.  I suspect it would work there, so all you would have to do is essentially duplicate your code, remove the check (because your validation will prevent focus from leaving if it isn't valid), and shift the focus in the CellLeave event.

Jake

Author

Commented:
I already did the below "CellLeave" but "e.Cancel" is not valid and leaving "e.Cancel" out causes it to loop forever.

How can I fix ?
--------------------------------------------------------------------------------
        private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                    e.Can
                }
            }
        }

Commented:
finanace_teacher,

You need to keep BOTH copies of the code, CellLeave & Validation as shown below.


        private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                {
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
            }
        }

private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                if (1 != 1) // stockNumber not found
                {
                      MessageBox.Show( "Stock Number not found" );
                    e.Cancel = true;
                }
            }
        }

Open in new window

Commented:
finance_teacher,

OH, sorry I see what you want to do now...  Let's use a variable mShiftFocus to indicate to the CellLeave event WHERE to shift focus, if validation has failed...  (I think that's what you want).

Try code attached.

Jake
        private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND" && mShiftFocus)
            {
                {
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
            }
        }

private bool mShiftFocus;

private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                if (1 != 1) // stockNumber not found
                {
                      MessageBox.Show( "Stock Number not found" );
                    mShiftFocus = True;
                }
            }
        }

Open in new window

Author

Commented:
I tried the below test #2,
but it still fails.

How can I get the cursor to
go into the 3rd column ?
--------------------------------------
TEST #1 --> 1 == 1
1. CellLeave runs
2. CellValidating runs
3. cursor stays in BRAND
   column if invalid, works
--------------------------------------
TEST #2 --> 1 != 1
1. CellLeave runs
2. CellValidating runs
3. cursor should go into
   3rd column, but fails
--------------------------------------
        private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                if (1 != 1) // stockNumber not found
                {
                    MessageBox.Show("Stock Number not found");
                    mShiftFocus = true;
                    e.Cancel = true;
                }
                else // stockNumber is found
                {
                    MessageBox.Show("Stock Number found");
                    //gML_BRANDDataGridView_CellLeave(null, null);
                }
            }
        }
--------------------------------------
        private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND" && mShiftFocus) //"CellLeave" runs before "CellValidating"
            {
                {
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
            }
        }

Commented:
finance_teacher,

My bad.  If your validation fails, and you MUST shift focus, you'll have to shift the focus, and remove the e.Cancel...  I don't know why you want to shift focus, that makes no sense to me (since the data IS NOT VALID), but that's what you'll have to do.

Jake


 private void gML_BRANDDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                if (1 != 1) // stockNumber not found
                {
                    MessageBox.Show("Stock Number not found");
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
                else // stockNumber is found
                {
                    MessageBox.Show("Stock Number found");
                }
            }
        }

Open in new window

Commented:
Ooops.

That will cause an endless loop =)  You really shouldn't be trying to do this shifting, however, I think it will work in Cell_Leave, so long as you don't want to force the user to EVER stay in the cell, that is, they must always have focus shifted...

Jake




private void gML_BRANDDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
{
            int vRowNumber = e.RowIndex;
            int vColumnNumber = e.ColumnIndex;
            string vColumnName = gML_BRANDDataGridView.Columns[e.ColumnIndex].DataPropertyName;

            if (vColumnName == "BRAND")
            {
                if (1 != 1) // stockNumber not found
                {
                    MessageBox.Show("Stock Number not found");
                    gML_BRANDDataGridView.CurrentCell = this.gML_BRANDDataGridView[3, 3];
                }
                else // stockNumber is found
                {
                    MessageBox.Show("Stock Number found");
                }
            }
        }

Open in new window

Commented:

hello everyone

I am getting this while running this code


Compiler Error Message: CS1061: 'System.Web.UI.WebControls.GridView' does not contain a definition for 'CurrentCell' and no extension method 'CurrentCell' accepting a first argument of type 'System.Web.UI.WebControls.GridView' could be found (are you missing a using directive or an assembly reference?)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial