Link to home
Start Free TrialLog in
Avatar of bigmacisdn
bigmacisdn

asked on

Validation of cells in Datagrid

Hi,
I am working on a simple purchase order system in VB.NET 2003
I have a dataset that has a purchase order header (purchtable) and the purchase order lines. (purchlines), joined on purchase Order number.

My form has 2 datagrids.  
The top datagrid is connected to purchtable, and shows a list of purchase orders.  
The bottom datagrid is connected to purchlines and shows the related lines of the purchase order.

When you click on a purchase order in the top grid, the lines of the purchase order automatically show in the bottom grid.

One of the fields in the purchase order line is an item number (ie Inventory Part number) .  (My system has another table of valid items that can be purchased.)

So, when the user keys in an item number, I want to validate the item number against the valid items table.  If it is not valid, I want to issue an error message (via msgbox,  or .SetColumnError or something)

The solution MUST cover the following situations;

The validation must occur when the user moves off the cell containing the item number.  (either via mouse or keyboard) .

If the field is in error, the user must not be able to move to another row in the grid or move the focus to any other part of the form (especially moving to another order by clicking on the order grid). Also the user must not be able to close the form with the item in error.

The cursor should be placed back on the item field in error.

The solution must cover the situation where the users moves to the end of the orderlines grid (creating a new record), and enters an invalid item.

Obviously I can do the actual item # validation code.  My question is more about the events (cellchanged, column changing) etc etc.  I just can't work it out.


Cheers

Neil Macpherson






Avatar of vbturbo
vbturbo
Flag of Denmark image

Hi

here is an approach that could cover the algorithm you are asking for.
A sort of sales line item (bussines rule)

1) populate your top grid with items to sell ,where user can pick from.
2) make a validation rule (in this case a row filter to the grid) so that the user is forced to filter out and pick an item before it can be entered in the bottum grid.
    that way you eliminate the IF (item number is valid) because of the picked(clicked) row in the top grid.
3) have an amount textbox where user can enter an amount to sell.
4) when entering a item in bottum grid validate check if validation rules are meet and add a new row in the dataset's table purchline if true.
    show entered items in bottum grid

nb. an enterkey_press when user moves up / down in the grid can easily be implemented to.




Imports System.Data.OleDb
Imports System.Windows.Forms.DataGrid.HitTestInfo
Imports System.Windows.Forms.DataGridTableStyle
 



Dim sStrVal as Boolean=False
Dim oDatarow As DataRow
Private Const TABLE_NAME As Object = "purchtable"

'declare your dataset.....etc.

'handle the picked out item, and set the first val rule to true
 Private Sub DataGrid1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGrid1.MouseDown
        Windows.Forms.Cursor.Current = Cursors.Hand
        Dim DataGrid1 As DataGrid = CType(sender, DataGrid)

        Dim hti As System.Windows.Forms.DataGrid.HitTestInfo
        hti = DataGrid1.HitTest(e.X, e.Y)
        Try
            lbl_item_id.Text = DataGrid1(hti.Row, 0).ToString()
            lbl_item_desc.Text  = DataGrid1(hti.Row, 1).ToString()
            lbl_item_price.Text  = DataGrid1(hti.Row, 2).ToString()
           
            'set sStrVal to true because it exsist's
            sStrVal=true
        Catch '//empty catch .. do nothing

        End Try
        amount_to_sell.Text = ""

    End Sub

    'filter on the items_id's in Datagrid1, maybee add one more txtfilter to be able to search for item_descriptions  also

    Private Sub txtFilter_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtFilter.TextChanged
 
        With dataset.Tables(TABLE_NAME)' items to pick from
            .DefaultView.RowFilter = "items_id like '" & txtFilter.Text & "%'"
            DataGrid1.DataSource = .DefaultView
        End With
    End Sub

' enter the picked item into bottum grid
   Private Sub Enteritem_in_Datagrid2()


        If sStrVal=False Then

            MsgBox("Missing information : " & vbCrLf & _
                                      "Chose a Product ?", MsgBoxStyle.Information Or _
                                      MsgBoxStyle.Question Or MsgBoxStyle.DefaultButton1, "Info")
            Exit Sub
        End If

        If  amount_to_sell.Text = "" Then

            MsgBox("Missing information  : " & vbCrLf & _
                                      "Please enter no. of items to purchase !", MsgBoxStyle.Information Or _
                                      MsgBoxStyle.Question Or MsgBoxStyle.DefaultButton1, "Info")
            Exit Sub
        End If

               ' add the purchased item into purchlines table in your dataset table "purchline"
                oDatarow = dataset.Tables("purchlines").NewRow()

                oDatarow.Item(0) = lbl_item_id.Text
                oDatarow.Item(1) = lbl_item_desc.Text
                oDatarow.Item(2) = lbl_item_price.Text


                dataset.Tables("purchlines").Rows.Add(oDatarow)
                Datagrid2.Datasource=dataset.Tables("purchlines")
    End Sub

' set some grid properties and collum width's
Private Sub SetTableStyleItemsGrid()

        Dim grdTableStyle1 As New DataGridTableStyle
        grdTableStyle1.MappingName = sDsName.Tables("purchlines").TableName

        grdTableStyle1.RowHeadersVisible = True ';
        grdTableStyle1.HeaderBackColor = Color.Lavender ';
        grdTableStyle1.HeaderBackColor = Color.SteelBlue ';//.FromArgb(8,36,107);
        grdTableStyle1.HeaderForeColor = Color.Black ';
        grdTableStyle1.GridLineColor = Color.SlateGray ';
        grdTableStyle1.BackColor = Color.LightSteelBlue
        DataGrid1.BackgroundColor = Color.White ';

        Dim Data1 As New DataGridTextBoxColumn
        Data1.MappingName = "item_id"
        Data1.HeaderText = "ID"
        Data1.Width = 20
        grdTableStyle1.GridColumnStyles.Add(Data1)

        Dim Data2 As New DataGridTextBoxColumn
        Data2.MappingName = "item_desc "
        Data2.HeaderText = "Product name."
        Data2.Width = 120
        grdTableStyle1.GridColumnStyles.Add(Data2)


        Dim Data3 As New DataGridTextBoxColumn
        Data3.MappingName = "item_price"
        Data3.HeaderText = "Price"
        Data3.Width = 60
        grdTableStyle1.GridColumnStyles.Add(Data3)


        DataGrid1.TableStyles.Add(grdTableStyle1)
    End Sub


hope you can use some of it

vbturbo
Avatar of bigmacisdn
bigmacisdn

ASKER

Thank for your response.

Unfortunately it doesn't help me much as I should have made two things clearer.

There are 1000's of items they can purchase, so any of form of picklist is not viable as it would be too slow and unwieldy.  

The user will key the item numbers directly into the orderline, (and they may change the item number on any order line at will)   The customer has a 'keyboard centric' approach to the data entry.  The item numbers are highly structured and the user can remember them quite easily.  It is a fairly high volume/speed data entry environment.

Thus, the validation must be done as the focus leaves the cell.



Hi

Yeah i see your solution-architecture ,needs some consideration.

Speed is the need here -:)

1) In my opinion ,working with disconected dataset is very adviseble (once it is populated ,the responce time is not be negotiated)

2) Consider that performance is 4x faster with typed(XSD) than untyped datasets (some say(though it is argued)) but in my opinon they are faster.

<<When you click on a purchase order in the top grid, the lines of the purchase order automatically show in the bottom grid.
<<One of the fields in the purchase order line is an item number (ie Inventory Part number)



But your idea with the validation issue (hmmm .. take another approach into consideration !) eighter there is such item or not(look up in the table),
in this case i would make a contextmenu availeble in bottum grid ["when purchase order line grid has focus"] (mouse right click or letter-key shortcut) E -for edit the item/ D- for deleting an item A- for adding an item ! Then popup one of 3 forms depending on user choice and handle it from there

1) if E is pressed(or clicked in contxtmenu) then popup the edit form and take the selected row data from purchlines.Grid with you (usually here it would bee an
    amount issue handling)

2) if A is pressed(or clicked in contxtmenu) do as mentioned above(1) and let the user type an item number that you would look up in the table to see wether it
    exist's or not ( if true ! show the item data in some labels or what ever - then enable an add button and validate the amount to purchase)
   (and that it is an integer)

3) as in 1,2 for deleting handling(primary key from the purchlines.Grid row (data) would be the one to delete


This way you'll have a friendly user interaction and in my opinion ???  more easy for the user to learn and implement.

Well it can be that i still have misunderstood the algorithm you are asking ,but this way it speeds responce time while only handling specific rows.

if you want some code to lookup rows in a dataset by primary keys or a select() + the usual crud methods then let know

well i know that this is not what you are asking for but hope you can see my point


vbturbo
Also it would save validation routines when the user for example moves down along the rows and each rows item number needs to be validated
before the next one can be selected..
Well

here one approach dealing with cell validation if you are determined to stick with your preliminary approach

download the 5.20 example solution

http://www.syncfusion.com/FAQ/WindowsForms/FAQ_c44c.aspx#q773q

vturbo
ASKER CERTIFIED SOLUTION
Avatar of vbturbo
vbturbo
Flag of Denmark image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Guys,

Sorry to not respond. I have been on vacation.

I actually solved it myself, as shown in the following generalised code snippet.


AddHandler DatasetPurchaseOrders1.Tables("Orderlines").ColumnChanging, AddressOf Column_Changing


Private Sub Column_Changing(ByVal sender As Object, ByVal e As System.Data.DataColumnChangeEventArgs)

Dim CurrentCell As String

e.Row.ClearErrors()

' validate certain columns

If (e.Column.ColumnName.Equals("Item")) Then

   CurrentCell = CType(e.ProposedValue, String)

   If (CurrrentCell = "invalid value")  Then

           MessageBox.Show("Value " + Trim(CurrentCell) + " is invalid.")
           
          ' put the old value back
           e.ProposedValue = e.Row(e.Column.ColumnName)

          ' signal row in error
           e.Row.RowError = "Value " + Trim(CurrentCell) + " is invalid."
           e.Row.SetColumnError(e.Column, "Item error")

  end if

end if

 


But I would like to award all points to VBTURBO


Cheers

Neil