Sunday, 14 April 2013

My Learnings with DataGridView in WinForms - Part 3

 Dynamically change images based on values based on other grid column
 
In this part, we will learn how to display appropriate images based on status(or any other grid column value). Let’s continue with the same code sample as in Part-2 and Part1.

Let’s consider a scenario that if a book is available we would like to display an image button “Buy” so that user can place order for that book. In case book is Not Available, we would let the user select “SMS” option so that whenever book is available user will be notified through SMS.

Status
ImageToDisplay
ImageIcon
Available
Buy
 


Not Available
SMS
                      
 

Let’s modify our grid in previous post to include one more column for Buy/SMS.
1.

 2.
 
3. New datagrid column will be added as shown.
 

4. Add CellFormatting event to the datagrid(dgvDashboard).
 
5.             Modify the code in dgvDashboard_CellMouseMove function as below. This function updates the mouse cursor to hand for newly added(Buy/SMS column).
 
private void dgvDashboard_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
        {
            //Skip the Column and Row header
            if (e.ColumnIndex < 0 || e.RowIndex < 0)
            {
                return;
            }
            //Check the condition as per the requirement casting the cell value to the appropriate type
            //column index 4 is delete column, column index 5 is Buy/SMS column
            if (e.ColumnIndex == 4 || e.ColumnIndex==5)
                dgvDashboard.Cursor = Cursors.Hand;
 else      {      dgvDashboard.Cursor = Cursors.Default;
}
6. Now add required images to the solution. Double  click on Resources.resx file from solution explorer.
 

Choose path of BuyNow and SMS images.
 
7.  Add the following code to cellformatting event.
private void dgvDashboard_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (!dgvDashboard.Rows[e.RowIndex].IsNewRow)
            {
                if (dgvDashboard.Columns[e.ColumnIndex].Name == "BuySMS")
                {
                    if ((dgvDashboard.Rows[e.RowIndex].Cells["Status"].Value).Equals("Available"))
                    {
                        e.Value = Properties.Resources.buy;
  dgvDashboard.Columns["BuySMS"].Tag = "Buy";
                    }
                    else
                    {
                        e.Value = Properties.Resources.sms;
  dgvDashboard.Columns["BuySMS"].Tag = "SMS";
                    }
                }
            }
        }
 
8. Let’s run the solution now and observe the output.
 

Oops!! Entire column contains “Buy” Image as status of all books is Available. To test properly lets change one of the row status to” NotAvailable”.
For this update the PopulateGrid() method as follows.
public IList<CourseEntity> PopulateGrid()
{
 List<CourseEntity> courseList = new List<CourseEntity>();
 courseList.Add(new CourseEntity { Id = "1", CourseName = "Asp.NET MVC3", Status = "Available" });
courseList.Add(new CourseEntity { Id = "2", CourseName = "Asp.NET MVC4", Status = "Available" });
courseList.Add(new CourseEntity { Id = "3", CourseName = "C#", Status = "Not Available" });
courseList.Add(new CourseEntity { Id = "4", CourseName = "Metro Apps", Status = "Available" });    
 return courseList;
 }
9. Now observe the output by running the solution again.

 
 Therefore, we are able to display appropriate images based on status column value. And also show hand cursor over them to make them clickable.
But nothing will happen as of now, if user clicks on BuyNow or SMS options. For that we need to write logic for “BuyNow” and SMS clicks.
Add the following code in MouseClick event of the datagrid.
private void dgvDashboard_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e){            //Skip the Column and Row headers
if (e.ColumnIndex < 0 || e.RowIndex < 0)  { return; }      
if (e.ColumnIndex == 4){  dgvDashboard.Rows.RemoveAt(e.RowIndex);}           
//if user click on Buy/SMS column   
         if (e.ColumnIndex == 5)            {
                //Add logic for Buy or SMS as per user selection
        if (dgvDashboard.Rows[e.RowIndex].Cells[e.ColumnIndex].Tag.Equals("Buy"))
                {
                    //Add logic for Buying the product
                    MessageBox.Show("You click on Buy Image in row " + e.RowIndex);
                }
                else
                {
                   //Add logic for sending sms
                    MessageBox.Show("You have clicked on SMS Image in row " + e.RowIndex);
                }
            }
        }
** Please notice that in step7 while assigning images to appropriate rows, we have also set tag property of image. This property helps us distinguish between Buy and SMS image clicks in same column.

Conclusion

We learnt how to dynamically change images based on values based on other grid column using cellFormatting Event.



Wednesday, 10 April 2013

My Learnings with DataGridView in WinForms - Part 2


In this post, I am going to explain how to use images as buttons for DataGridView. We will work on the DataGridView used in part1  for this purpose.
1.       Include one Image column Delete in DataGridView as follows.

 


 
2.       Open DataGridView Tasks>Edit Columns.
 
3.       Click Delete in the Selected Column section.
4.       Select Image in Unbound Column Properties section to specify path of image for the Delete column.


            You can either specify the image path from the resources file or import the image from a
local resource.



5.       Notice that Image property is now set to the selected path.


6.       Click OK to save the changes.
7.       Run the solution.


Notice that the Delete column appears as an image column. However, if you mouse over the Delete column, it appears like a normal column.


To make the Delete column look like a button when mouse moves over the cells of the image column, define a CellMouseMove event and set the cursor to Hand cursor.

8.       In the DataGridView properties, define CellMouseMove and CellMouseClick events for the DataGridView with the name dgvDashboard.
 


9.       Add the following code to the Dashboard.cs file.

private void dgvDashboard_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
        {
            //Skip the Column and Row headers
            if (e.ColumnIndex < 0 || e.RowIndex < 0)
            {
                return;
            }

            //Check the condition as per the requirement casting the cell value to the appropriate type
       // here 4 represents delete column index in grid starting from 0th column
            if (e.ColumnIndex == 4)
                dgvDashboard.Cursor = Cursors.Hand;
            else
                dgvDashboard.Cursor = Cursors.Default;
        }
 

  Notice that when you mouse over the cells of the Delete column, the cursor changes to the hand cursor.



Also notice that when you mouse over the cells of the other columns, the cursor will be a default one.


Now the Delete column looks like an image button column, but we still have to define Click event for the cells in the Delete column.
To define Click event for the cells in the Delete column, add CellMouseClick event for DataGridView and add the following code in Dashboard.cs file.

private void dgvDashboard_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            //Skip the Column and Row headers
            if (e.ColumnIndex < 0 || e.RowIndex < 0)
            {
                return;
            }
            if (e.ColumnIndex == 4)
            {
                dgvDashboard.Rows.RemoveAt(e.RowIndex);
            }
        }
10.       Run the application and delete a row from the grid on the Dashboard form.



After you delete the second row, the new grid appears as seen in the following figure.

 

Conclusion

In this post, we have seen how to add image columns and define click events for them. We also learnt about events like CellMouseClick and CellMouseMove.
In the next post, I will explain how to dynamically change images based on the status or column of a grid. Stay tuned J