ThinkGeo.com    |     Documentation    |     Premium Support

Rendering Custom Data Web 3.0 Sample Code

Hi


I try to convert the following 2.0 code to web 3.0.  Can anyone help me and provide me a sample?


Thanks.


tgMap1.Layers(0).CustomFields.Clear()



            For Each dr In dsTractData1.TractData.Rows

                hashTable.Add(dr.FIPS, dr.income_lvl)

                hashTable1.Add(dr.FIPS, dr.Loan_Cnt)

                hashTable2.Add(dr.FIPS, dr.Loan_Amt)

                hashTable3.Add(dr.FIPS, dr.minority_p)

                hashTable4.Add(dr.FIPS, dr.sbsf_total)

                hashTable5.Add(dr.FIPS, dr.D_AREA)

                hashTable6.Add(dr.FIPS, dr.U_AREA)

            Next



            Dim customField As CustomField = New CustomField

            ' Clear any exiting custom fields.

            'tgMap1.Layers(0).CustomFields.Clear()



            ' The column that contains our custom data.

            customField.CustomFieldName = "income_lvl"



            ' The column that is in th shape file for our map.

            customField.LinkFieldName = "FIPS"

            customField.CustomData = hashTable



            ' Add the custom field to the layer.

            tgMap1.Layers(0).CustomFields.Add("income_lvl", customField)



            Dim customField1 As CustomField = New CustomField

            customField1.CustomFieldName = "Loan_Cnt"

            customField1.LinkFieldName = "FIPS"

            customField1.CustomData = hashTable1

            tgMap1.Layers(0).CustomFields.Add("Loan_Cnt", customField1)



            Dim customField2 As CustomField = New CustomField

            customField2.CustomFieldName = "Loan_Amt"

            customField2.LinkFieldName = "FIPS"

            customField2.CustomData = hashTable2

            tgMap1.Layers(0).CustomFields.Add("Loan_Amt", customField2)



            Dim customField3 As CustomField = New CustomField

            customField3.CustomFieldName = "minority_p"

            customField3.LinkFieldName = "FIPS"

            customField3.CustomData = hashTable3

            tgMap1.Layers(0).CustomFields.Add("minority_p", customField3)


................................



Hi Kevin,



In Map Suite Web 3.0, CustomFields is added from an event which rises when fields are requested in a FeatureSource method that doesn’t exist in the FeatureSource.

Please see the attached code for detail,

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    If Not Page.IsPostBack Then
        tgMap1.CurrentExtent = New RectangleShape(-140, 60, 140, -60)
        tgMap1.MapBackground.BackgroundBrush = New GeoSolidBrush(GeoColor.FromHtml("#B3C6D4"))
        tgMap1.MapUnit = GeographyUnit.DecimalDegree
        
        Dim worldLayer As New ShapeFileFeatureLayer(MapPath("~\SampleData\World\cntry02.shp"))
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1)
        worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        worldLayer.DrawingMarginPercentage = 50
        
        AddHandler worldLayer.FeatureSource.CustomColumnFetch, AddressOf FeatureSource_CustomColumnFetch
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("income_lvl")
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("Loan_Cnt")
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("Loan_Amt")
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("minority_p")
        tgMap1.StaticOverlay.Layers.Add(worldLayer)
    End If
End Sub

Protected Sub FeatureSource_CustomColumnFetch(ByVal sender As Object, ByVal e As CustomColumnFetchEventArgs)
    Dim rowIndex As Integer = Int32.Parse(e.Id)
    Dim currentDataRow As DataRow = dsTractData1.TractData.Rows(rowIndex)
    
    Select Case e.ColumnName
        Case "income_lvl"
            e.ColumnValue = currentDataRow.income_lvl
            Exit Select
        Case "Loan_Cnt"
            e.ColumnValue = currentDataRow.Loan_Cnt
            Exit Select
        Case "Loan_Amt"
            e.ColumnValue = currentDataRow.Loan_Amt
            Exit Select
        Case "minority_p"
            e.ColumnValue = currentDataRow.minority_p
            Exit Select
    End Select
End Sub

If you have any queries please let me know.



Thanks,



Howard



Thanks, Howard,


But it doesn't work.  The row count of my table is much less then the row count in attribute table.  I cannot use e.id to get the correct row in my dataset.  Please see the following code.


In a real case, I only need to retrieve a small set of data from my tract table and render these tract on map.  (ie.  tracts in one county).


I don't want to retrieve all tracts in US that will be too slow and us too much  memory.


In 2.0 I only need retrieve few tracts and insert them into a hashTable, then link this hashTable to the customField.


To solve this issue, I might have to add a ID column in my sql table.  But I have to maintain the IDs that have to match the id in tracts layer attribute table.  Finding a row in a dataset whose ID matches e.id is also slow.


    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

        If Not Page.IsPostBack Then

            Map1.CurrentExtent = New RectangleShape(-140, 60, 140, -60)

            Map1.MapBackground.BackgroundBrush = New GeoSolidBrush(GeoColor.FromHtml("#B3C6D4"))

            Map1.MapUnit = GeographyUnit.DecimalDegree



            

            Dim worldLayer As New ShapeFileFeatureLayer(MapPath("~\SampleData\World\cntry02.shp"))

            worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1)

            worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20

            worldLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Country1("Income_Lvl")



            AddHandler worldLayer.FeatureSource.CustomColumnFetch, AddressOf FeatureSource_CustomColumnFetch

            worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("Income_Lvl")

            Map1.StaticOverlay.Layers.Add(worldLayer)



            Dim dr As dsCntry.CNTRYRow



            dr = dsCntry1.CNTRY.NewRow

            dr.FIPS_CNTRY = "US"

            dr.Income_Lvl = "Upper"



            dsCntry1.CNTRY.Rows.Add(dr)

        End If

    End Sub



    Private Sub FeatureSource_CustomColumnFetch(ByVal sender As Object, ByVal e As CustomColumnFetchEventArgs)

        Dim rowIndex As Integer = Int32.Parse(e.Id)

        Dim currentDataRow As dsCntry.CNTRYRow = dsCntry1.CNTRY.Rows(rowIndex)



        Select Case e.ColumnName

            Case "Income_Lvl"

                e.ColumnValue = currentDataRow.Income_Lvl

                Exit Select

        End Select

    End Sub



Kevin,



Loading from Database whenever raise this event is terrible slow, how about use the following idea:
Dim features As Collection(Of Feature) = worldLayer.FeatureSource.GetFeaturesInsideBoundingBox(Map1.CurrentExtent, ReturningColumnsType.NoColumns)
// Select the data which match the id from database.
// Save the data in memory such as session.
// When the event raise again, just load it.
// But you need to clear the session when the extent changed.
...

Any questions please let me know,



Thanks,



Howard



Thanks, Howard, 
  
 I might have to load all the attribute files into my SQL database and add a ID column into each attribute table.  Loading and maintaining these tables will be extra works for me.  I still like 2.0 way that allows me to add my data into a layer by linking their FIPS with the FIPS of the shapefile. 
  
 Thanks.

Hi Kevin,



You are right my old method is not a good way; here I have a better idea just like your old logic. In 2.0, it’s a simple API to implement your scenario, but you can’t handle much about this, while in 3.0, we want user to know more about this logic and you can handle more about this.



In the following code, I made a dictionary to save the relationship between ID and FIPS and then you can maintain your logic as your old way.

Private correspondings1 As New Dictionary(Of String, String)()
Private correspondings2 As New Dictionary(Of String, Dictionary(Of String, String))()

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    If Not Page.IsPostBack Then
        tgMap1.CurrentExtent = New RectangleShape(-140, 60, 140, -60)
        tgMap1.MapBackground.BackgroundBrush = New GeoSolidBrush(GeoColor.FromHtml("#B3C6D4"))
        tgMap1.MapUnit = GeographyUnit.DecimalDegree
        
        Dim worldLayer As New ShapeFileFeatureLayer(MapPath("~\SampleData\World\cntry02.shp"))
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(255, 243, 239, 228), GeoColor.FromArgb(255, 218, 193, 163), 1)
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("income_lvl")
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("Loan_Cnt")
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("Loan_Amt")
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.RequiredColumnNames.Add("minority_p")
        worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        worldLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Country1("Test")
        worldLayer.DrawingMarginPercentage = 50
        
        AddHandler worldLayer.FeatureSource.CustomColumnFetch, AddressOf FeatureSource_CustomColumnFetch
        tgMap1.StaticOverlay.Layers.Add(worldLayer)
        
        ' correspond the ID and FIPS.
        Dim dataSource As DataTable = worldLayer.QueryTools.ExecuteQuery("Select RECID, FIPS from cntry02")
        For Each row As DataRow In dataSource.Rows
            correspondings1(row("RECID").ToString()) = row("FIPS").ToString()
        Next
        
        ' initialise the hashtables in your code.
        correspondings2("income_lvl") = New Dictionary(Of String, String)()
        correspondings2("Loan_Cnt") = New Dictionary(Of String, String)()
        correspondings2("Loan_Amt") = New Dictionary(Of String, String)()
        correspondings2("minority_p") = New Dictionary(Of String, String)()
        
        For Each dr As DataRow In dsTractData1.TractData.Rows
            correspondings2("income_lvl").Add(dr.FIPS, dr.income_lvl)
            correspondings2("Loan_Cnt").Add(dr.FIPS, dr.Loan_Cnt)
            correspondings2("Loan_Amt").Add(dr.FIPS, dr.Loan_Amt)
            correspondings2("minority_p").Add(dr.FIPS, dr.minority_p)
        Next
        
        Session("Correspondings1") = correspondings1
        Session("Correspondings2") = correspondings2
    End If
End Sub

Protected Sub FeatureSource_CustomColumnFetch(ByVal sender As Object, ByVal e As CustomColumnFetchEventArgs)
    correspondings1 = DirectCast(Session("Correspondings1"), Dictionary(Of String, String))
    correspondings2 = DirectCast(Session("Correspondings2"), Dictionary(Of String, Dictionary(Of String, String)))
    
    Dim fips As String = correspondings1(e.Id)
    
    Select Case e.ColumnName
        Case "income_lvl"
            e.ColumnValue = correspondings2(e.ColumnName)(fips)
            Exit Select
        Case "Loan_Cnt"
            e.ColumnValue = correspondings2(e.ColumnName)(fips)
            Exit Select
        Case "Loan_Amt"
            e.ColumnValue = correspondings2(e.ColumnName)(fips)
            Exit Select
        Case "minority_p"
            e.ColumnValue = correspondings2(e.ColumnName)(fips)
            Exit Select
        Case Else
            Exit Select
    End Select
End Sub

If you have anymore questions please let me know.



Thanks,



Howard





  What a brilliant idea! Thanks.



Hi Kevin, 
  
 Great! You are welcome, if you have more queries please let me know. 
  
 Thanks, 
  
 Howard