简体   繁体   中英

C# WPF DataGrid Search for a Value in a Column, Return the Row Index

I am new at C# development. I am learning and struggling as I am writing an application - the best way to learn is by doing : )

I hope that someone will be able to assist me with my issue.

I am populating the WPF DataGrid via the dataGrid1.ItemsSource = dt.DefaultView; and then letting the DataGrid automatically generate the columns for me.

The user is able to click on any row in the DataGrid which will then populate the header section that I have on the WPF UI with the row's data - this allows the user to edit the row via the header. I do not want them to edit via the DataGrid.

The user is able to edit the row via the header fields and then click on an UPDATE button. The UPDATE button will run a stored procedure which handles all validations and updating of the record. Once the record is saved I fire off the grid refresh method.

Once the grid is refreshed I need to be able to search on a specific column on the DataGrid in order to Select, set Focus and scroll into the row that just got updated.

I have searched like crazy on Google and I just cannot find how to do this on the DataGrid. There are samples on how to do it on the DataGridView which is not what I am using.

Any help is greatly appreciated....thanks

This is my code for the Button Click

private void btn_Update_Click(object sender, RoutedEventArgs e) {

        // variables
        bool isOkToUpdate = true;

        this.Cursor = Cursors.Wait;            

        // Validations of certain fields
        if (txt_FinanceEmpName.Text.Length > 25 )
        {
            MessageBox.Show("The Finance Emp Name must not exceed 25 characters in length. " 
                + txt_FinanceEmpName.Text.Length.ToString()
                , "Maximum characters exceeded"
                , MessageBoxButton.OK, MessageBoxImage.Stop);

            isOkToUpdate = false;
        }

        //
        if (isOkToUpdate == true)
        {
            // create an instance
            DatabaseClass objDatabaseClass = new DatabaseClass(_connectionString);

            // if we are able to open and close the SQL Connection then proceed
            if (objDatabaseClass.CheckSQLConnection())
            {
                try
                {
                    // create instance of SqlConnection class. variable 'con' will hold the instance
                    SqlConnection con = new SqlConnection(_connectionString);

                    con.Open();

                    // use a using for all disposable objects, so that you are sure that they are disposed properly
                    using (SqlCommand cmd = new SqlCommand("usp_mktdata_update_cm_mktdata_emp_name_fits_to_finance", con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.Add("@IdUnique", SqlDbType.Int).Value = Convert.ToInt32(txt_IdUnique.Text);
                        cmd.Parameters.Add("@FinanceEmpName", SqlDbType.VarChar).Value = txt_FinanceEmpName.Text;
                        cmd.Parameters.Add("@ADWindowsLogon", SqlDbType.VarChar).Value = _windowsUserName;
                        cmd.Parameters.Add("@ADWindowsLogonEMail", SqlDbType.VarChar).Value = _windowsUserNameEMail;
                        cmd.Parameters.Add("@IndActive", SqlDbType.TinyInt).Value = 1;
                        cmd.Parameters.Add("@RecordVersion", SqlDbType.Int).Value = Convert.ToInt32(txt_RecordVersion.Text);
                        //cmd.Parameters.Add("@IdJob", SqlDbType.Int).Value = "DEFAULT";
                        //cmd.Parameters.Add("@IdUser", SqlDbType.Int).Value = "DEFAULT";
                        //cmd.Parameters.Add("@outIdUnique", SqlDbType.Int).Value = "DEFAULT";
                        //cmd.Parameters.Add("@outRecordVersion", SqlDbType.Int).Value = "DEFAULT";
                        //cmd.Parameters.Add("@outInd", SqlDbType.Int).Value = "DEFAULT";
                        //cmd.Parameters.Add("@outMessage", SqlDbType.VarChar).Value = "DEFAULT";

                        cmd.ExecuteNonQuery();
                    }

                    // Last Updated Record
                    txt_LastUpdated_IdUnique.Text = txt_IdUnique.Text;
                    txt_LastUpdated_FitsEmpName.Text = txt_FitsEmpName.Text;
                    txt_LastUpdated_FinanceEmpName.Text = txt_FinanceEmpName.Text;

                    // Refresh the Datagrid - the DataGrid_MonikerName
                    // pass in null for the params in order to fire the event
                    btn_RefreshGrid_Click(null, null);



                    // ****************************************
                // TODO:  After Grid Refresh Search the column ID UNIQUE for the value stored in txt_IdUnique.Text which
                //  was just saved via the stored procedure
                // Once the value is found in the DataGrid need to grab the DataGrid Row INdex in order to 
                // Select the ROW and Set the ROW to the SELECTED ROW and set focus to the DataGrid also will need to Scroll the Grid into View.
                    //
                    // ****************************************


                    con.Close();
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.ToString());                    
                }
            }
            else
            {
                MessageBox.Show("Connection not established to the SQL Server. " + Environment.NewLine + "The SQL Server may be offline or valid credentials are not yet granted.", "SQL Server Connection Error", MessageBoxButton.OK, MessageBoxImage.Error);

                this.Close();
            }
        }   

        this.Cursor = Cursors.Arrow;
    }

I too work with DataTable.DefaultView for the grids in our system. I have also sub-classed the DataGrid for "MyDataGrid"... On the MyDataGrid, I have a custom method to force loading the given ID based on its primary key. So I have another custom property on the grid for what is the name of the primary key column as it should be found within the dataview, even though it may not be visually shown in the grid.

Based on what you supplied, here is a modification from my original code to your specific environment...

public void TryGridRefresh()
{
   int IDToFind = Convert.ToInt32(txt_IdUnique.Text);

   if (IDToFind > -1 && dataGrid1.ItemsSource is DataView )
   {
      foreach( DataRowView drv in (DataView)dataGrid1.ItemsSource )
         if ((int)drv["IdUnique"] == IDToFind)
         {
            // This is the data row view record you want...
            dataGrid1.SelectedItem = drv;
         }
   }
}

So, just after your call to

 btn_RefreshGrid_Click(null, null);

then call

TryGridRefresh();

I have my data grids as an entire ROW for the selected value instead of per-cell. So you may need to play around with the object references a bit... Once you find the row, you may also try with dataGrid1.CurrentItem...

Hopefully this will get you closer to your final resolution.

 public void TryGridRefresh(string IdUniqueToFind, DataGrid MyDataGrid, string MyGridColumnToSearch)
    {  
        int IDToFind = Convert.ToInt32(IdUniqueToFind);

// this if did not work for me..got errors  
        //if (IDToFind > -1) and (dataGrid_MonikerName.ItemsSource is DataView )
        //{
        foreach (DataRowView drv in (DataView)MyDataGrid.ItemsSource)
        {               
            if ((int)drv[MyGridColumnToSearch] == IDToFind)
            {
                // This is the data row view record you want...
                MyDataGrid.SelectedItem = drv;

                MyDataGrid.ScrollIntoView(drv);
                MyDataGrid.Focus();

                break;
            }
        }
    }       

The Method is then called like so after the grid refresh call - TryGridRefresh(txt_LastUpdated_IdUnique.Text, dataGrid_MonikerName, gridData_ColumnToSearch);

I also had to change the
datagrid DataRowView from CurrentCell.Item to SelectedItem in order to capture the entire row for the selected value instead of per-cell.

//DataRowView _DataView = dataGrid_MonikerName.CurrentCell.Item as DataRowView; DataRowView _DataView = dataGrid_MonikerName.SelectedItem as DataRowView;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM