From: Scott on 8 Apr 2010 11:52 When populating a Treeview in code, I am getting "duplicate" nodes. They appear in the treeview, but don't seem to exist when I iterate through the node collections. This is what I get: http://www.emick.us/Capture.JPG and this is my code. I am baffled. Scott Emick Public Class MainForm Private Sub ProcessButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ProcessButton.Click Dim ds1 As New DS Dim cn As New SqlConnection(My.Settings.WINDY) cn.Open() Dim cmd As New SqlCommand cmd.Connection = cn cmd.CommandText = "SELECT coalesce([MASTER NUMBER],-1) AS MASTER_NUMBER FROM SALESTRANSACTIONS WHERE [SOP NUMBER] = '" & OrderNumberTextBox.Text & "'" Dim MasterNumber As Integer = cmd.ExecuteScalar cmd.CommandText = "SELECT [SOP NUMBER], [ORIGINAL NUMBER] FROM SALESTRANSACTIONS WHERE [MASTER NUMBER] = " & MasterNumber Dim da As New SqlDataAdapter(cmd) da.Fill(ds1.OrderTree) For rc As Integer = 0 To (ds1.OrderTree.Count - 1) Dim dr As DS.OrderTreeRow = ds1.OrderTree(rc) If dr.ORIGINAL_NUMBER = "" Then OrderTreeView.Nodes.Add(dr.SOP_NUMBER) Console.WriteLine(dr.SOP_NUMBER) OrderTreeView.ExpandAll() Application.DoEvents() Else 'try to find the node to add to For tc As Integer = 0 To (OrderTreeView.Nodes.Count - 1) Dim rn As TreeNode = FindNode(dr.ORIGINAL_NUMBER, OrderTreeView.Nodes(tc)) If Not rn Is Nothing Then rn.Nodes.Add(dr.SOP_NUMBER) OrderTreeView.ExpandAll() Application.DoEvents() Exit For End If Next End If Next End Sub Private Function FindNode(ByRef Original_Number As String, ByRef nd As TreeNode) As TreeNode If nd.Text = Original_Number Then Return nd End If If nd.Nodes.Count > 0 Then For Each sn As TreeNode In nd.Nodes Dim rn As TreeNode = FindNode(Original_Number, sn) If Not rn Is Nothing Then Return rn End If Next End If Return Nothing End Function
From: Scott on 8 Apr 2010 11:55 Funny I changed my arguments to the FindNode function from ByRef to ByVal and the problems has stopped. Very odd. Private Function FindNode(ByVal Original_Number As String, ByVal nd As TreeNode) As TreeNode On Apr 8, 11:52 am, Scott <scott.em...(a)gmail.com> wrote: > When populating a Treeview in code, I am getting "duplicate" nodes. > They appear in the treeview, but don't seem to exist when I iterate > through the node collections. > > This is what I get: > > http://www.emick.us/Capture.JPG > > and this is my code. I am baffled. > > Scott Emick > > Public Class MainForm > Private Sub ProcessButton_Click(ByVal sender As System.Object, > ByVal e As System.EventArgs) Handles ProcessButton.Click > Dim ds1 As New DS > Dim cn As New SqlConnection(My.Settings.WINDY) > cn.Open() > Dim cmd As New SqlCommand > cmd.Connection = cn > cmd.CommandText = "SELECT coalesce([MASTER NUMBER],-1) AS > MASTER_NUMBER FROM SALESTRANSACTIONS WHERE [SOP NUMBER] = '" & > OrderNumberTextBox.Text & "'" > Dim MasterNumber As Integer = cmd.ExecuteScalar > cmd.CommandText = "SELECT [SOP NUMBER], [ORIGINAL NUMBER] FROM > SALESTRANSACTIONS WHERE [MASTER NUMBER] = " & MasterNumber > Dim da As New SqlDataAdapter(cmd) > da.Fill(ds1.OrderTree) > For rc As Integer = 0 To (ds1.OrderTree.Count - 1) > Dim dr As DS.OrderTreeRow = ds1.OrderTree(rc) > If dr.ORIGINAL_NUMBER = "" Then > OrderTreeView.Nodes.Add(dr.SOP_NUMBER) > Console.WriteLine(dr.SOP_NUMBER) > OrderTreeView.ExpandAll() > Application.DoEvents() > Else > 'try to find the node to add to > For tc As Integer = 0 To (OrderTreeView..Nodes.Count - > 1) > Dim rn As TreeNode = FindNode(dr.ORIGINAL_NUMBER, > OrderTreeView.Nodes(tc)) > If Not rn Is Nothing Then > rn.Nodes.Add(dr.SOP_NUMBER) > OrderTreeView.ExpandAll() > Application.DoEvents() > Exit For > End If > > Next > End If > Next > End Sub > Private Function FindNode(ByRef Original_Number As String, ByRef > nd As TreeNode) As TreeNode > If nd.Text = Original_Number Then > Return nd > End If > If nd.Nodes.Count > 0 Then > For Each sn As TreeNode In nd.Nodes > Dim rn As TreeNode = FindNode(Original_Number, sn) > If Not rn Is Nothing Then > Return rn > End If > Next > End If > Return Nothing > End Function
From: Patrice on 8 Apr 2010 14:12 > Funny I changed my arguments to the FindNode function from ByRef to > ByVal and the problems has stopped. Very odd. This is expected. The recursive FindNode calls behaves as if you are doing nd=sn and then OrderTreeView.Nodes(tc)=nd... Keep in mind that ByRef still passes the original value while ByVal transmits a copy... Though it doesn't make a difference when accessing object members (a pointer (which is basically what an object is) or the copy of a pointer still points to the same location), changing the object argument itself still does (i.e you change the pointer itself). As here you obviously didn't want to change anything, why to use ByRef as a default ? I would suggest always using ByVal as a default... -- Patrice
From: Scott on 9 Apr 2010 08:18 On Apr 8, 2:12 pm, "Patrice" <http://www.chez.com/scribe/> wrote: > > Funny I changed my arguments to the FindNode function from ByRef to > > ByVal and the problems has stopped. Very odd. > > This is expected. The recursive FindNode calls behaves as if you are doing > nd=sn and then OrderTreeView.Nodes(tc)=nd... > > Keep in mind that ByRef still passes the original value while ByVal > transmits a copy... > > Though it doesn't make a difference when accessing object members (a pointer > (which is basically what an object is) or the copy of a pointer still points > to the same location), changing the object argument itself still does (i.e > you change the pointer itself). > > As here you obviously didn't want to change anything, why to use ByRef as a > default ? I would suggest always using ByVal as a default... > > -- > Patrice I normally do use byval as a default... Normally the only reasons I use ByRef is either to change something like you said, or also if the object is very large like a huge dataset or something it seems like a waste to make a copy of it. But once in a great while, I get "creative" when doing some ad-hoc coding....
From: Scott on 9 Apr 2010 08:29
On Apr 9, 8:18 am, Scott <scott.em...(a)gmail.com> wrote: > On Apr 8, 2:12 pm, "Patrice" <http://www.chez.com/scribe/> wrote: > > > > > > Funny I changed my arguments to the FindNode function from ByRef to > > > ByVal and the problems has stopped. Very odd. > > > This is expected. The recursive FindNode calls behaves as if you are doing > > nd=sn and then OrderTreeView.Nodes(tc)=nd... > > > Keep in mind that ByRef still passes the original value while ByVal > > transmits a copy... > > > Though it doesn't make a difference when accessing object members (a pointer > > (which is basically what an object is) or the copy of a pointer still points > > to the same location), changing the object argument itself still does (i.e > > you change the pointer itself). > > > As here you obviously didn't want to change anything, why to use ByRef as a > > default ? I would suggest always using ByVal as a default... > > > -- > > Patrice > > I normally do use byval as a default... > > Normally the only reasons I use ByRef is either to change something > like you said, or also if the object is very large like a huge dataset > or something it seems like a waste to make a copy of it. > > But once in a great while, I get "creative" when doing some ad-hoc > coding.... And in case anyone else ever has use for some code that displays order hierarchy in Dynamics GP - Great Plains this is the code that ended up working. I was just doing for myself, so yes it is sloppy! If I end up using the logic in one of my projects I will probably create a class in a library that returns an xml representation of the sop document heirarchy and then use that for whatever purpose I need it such as finding the status of individual items from a web order that has been fulfilled through great plains. Private Sub ProcessButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ProcessButton.Click OrderTreeView.Nodes.Clear() Dim ds1 As New DS Dim cn As New SqlConnection(My.Settings.WINDY) cn.Open() Dim cmd As New SqlCommand cmd.Connection = cn cmd.CommandText = "SELECT coalesce([MASTER NUMBER],-1) AS MASTER_NUMBER FROM SALESTRANSACTIONS WHERE [SOP NUMBER] = '" & OrderNumberTextBox.Text & "'" Dim MasterNumber As Integer = cmd.ExecuteScalar cmd.CommandText = "SELECT [SOP NUMBER], [ORIGINAL NUMBER], [sop type] FROM SALESTRANSACTIONS " & _ " WHERE [MASTER NUMBER] = " & MasterNumber & " order by [original number]" Dim da As New SqlDataAdapter(cmd) da.Fill(ds1.OrderTree) Dim otr As DS.OrderTreeRow() = ds1.OrderTree.Select("[ORIGINAL NUMBER]=''") If otr.Length > 0 Then Dim SOP_NUMBER As String = otr(0).SOP_NUMBER Dim SOP_TYPE As String = otr(0).sop_type Dim curnode As TreeNode = OrderTreeView.Nodes.Add(SOP_NUMBER & " (" & SOP_TYPE & ")") curnode.Expand() ListNodeItems(SOP_NUMBER, SOP_TYPE, curnode) FindChildren(curnode, ds1.OrderTree, SOP_NUMBER) End If End Sub Private Sub FindChildren(ByVal curnode As TreeNode, ByVal ot As DS.OrderTreeDataTable, ByVal SOP_NUMBER As String) Dim otr As DS.OrderTreeRow() = ot.Select("[ORIGINAL NUMBER]='" & SOP_NUMBER & "'") If otr.Length > 0 Then For cc As Integer = 0 To (otr.Length - 1) Dim newnode As TreeNode = curnode.Nodes.Add(otr(cc).SOP_NUMBER & " (" & otr(cc).SOP_TYPE & ")") newnode.Expand() ListNodeItems(otr(cc).SOP_NUMBER, otr(cc).SOP_TYPE, newnode) FindChildren(newnode, ot, otr(cc).SOP_NUMBER) Next End If End Sub Private Sub ListNodeItems(ByVal SOP_NUMBER As String, ByVal SOP_TYPE As String, ByVal curnode As TreeNode) Dim gvaOrderTypes As New DS.gvaOrderTypesDataTable Dim gvaOrderTypesTA As New DSTableAdapters.gvaOrderTypesTA gvaOrderTypesTA.Fill(gvaOrderTypes) Dim sli As New DS.SOPLINEITEMSDataTable Dim sli_table_adapter As New DSTableAdapters.SOPLINEITEMSTA Dim otr As DS.gvaOrderTypesRow() = gvaOrderTypes.Select("OrderTypeDesc = '" & SOP_TYPE & "'") Dim sop_type_key As Integer = otr(0).OrderType sli_table_adapter.Fill(sli, SOP_NUMBER, sop_type_key) For Each li As DS.SOPLINEITEMSRow In sli.Rows Dim itemnmbr As TreeNode = curnode.Nodes.Add(li.ITEMNMBR) itemnmbr.Nodes.Add("QUANTITY " & li.QUANTITY) itemnmbr.Nodes.Add("QTYCANCE " & li.QTYCANCE) itemnmbr.Nodes.Add("QTYFULFI " & li.QTYFULFI) itemnmbr.Nodes.Add("QTYTBAOR " & li.QTYTBAOR) itemnmbr.Nodes.Add("QTYTOINV " & li.QTYTOINV) Next End Sub Private Function FindNode(ByVal Original_Number As String, ByVal nd As TreeNode) As TreeNode If nd.Text = Original_Number Then Return nd End If If nd.Nodes.Count > 0 Then For Each sn As TreeNode In nd.Nodes Dim rn As TreeNode = FindNode(Original_Number, sn) If Not rn Is Nothing Then Return rn End If Next End If Return Nothing End Function -- Yes this table should be called SOPTypes, not ordertypes.......This is the table for the SOPTYPE lookup CREATE TABLE [dbo].[gvaOrderTypes]( [OrderType] [int] NOT NULL, [OrderTypeDesc] [varchar](255) NOT NULL, CONSTRAINT [PK_gvaOrderTypes] PRIMARY KEY CLUSTERED ( [OrderType] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO INSERT [dbo].[gvaOrderTypes] ([OrderType], [OrderTypeDesc]) VALUES (1, N'Quote') INSERT [dbo].[gvaOrderTypes] ([OrderType], [OrderTypeDesc]) VALUES (2, N'Order') INSERT [dbo].[gvaOrderTypes] ([OrderType], [OrderTypeDesc]) VALUES (3, N'Invoice') INSERT [dbo].[gvaOrderTypes] ([OrderType], [OrderTypeDesc]) VALUES (4, N'Return') INSERT [dbo].[gvaOrderTypes] ([OrderType], [OrderTypeDesc]) VALUES (5, N'Back Order') |