Select to view content in your preferred language

Problems refreshing map - VB.net Editor Extension

2962
6
Jump to solution
04-26-2012 05:12 AM
RebeccaZeckoski
Occasional Contributor
I can't seem to find anyone else with this problem, but I'm hoping maybe I'm missing something obvious!

I am writing an Editor Extension add-in using VB.net for ArcMap 10.

Once the user starts editing, I use a unique value renderer to display features, omitting some (the client wants features they have classified as 'inactive' to disappear - without being deleted - and my understanding is that a definition query won't work in an edit session, so I have modified the symbology instead).

After I set the renderer, I want the display to refresh to show the new symbology.  However, ActiveView.Refresh, ActiveView.PartialRefresh, and ScreenDisplay.Invalidate will not work.  There is no error, but the screen does not refresh.  I have stepped through using the debugger and confirmed that the program execution does reach those lines, but after 'executing' those lines nothing happens.  The TOC updates properly, but the view does not.  I can manually click the refresh button and it refreshes just fine, but I can't seem to make it work programmatically.

I have tried brute forcing it by using ActiveView.Deactivate followed by ActiveView.Activate, and this does cause a screen refresh, but then when I try to draw the point, the mouse pointer and the marker symbol indicating the potential location of the new point are offset by about 4 inches.

I'm completely at a loss here.  Any ideas?

I've included an exerpt from my code below (this is done nearly identically for 4 feature layers, so normally the select case would have 3 more entries, but I simplified it for this post).  Thanks!!

        'define the colors to use in the renderers
        Dim pOutlineColor As New ESRI.ArcGIS.Display.RgbColor
        Dim pStructureColor As New ESRI.ArcGIS.Display.RgbColor
       
        'make the structure outline color black
pOutlineColor.Red = 0
pOutlineColor.Blue = 0
pOutlineColor.Green= 0

'make the structure center color macaw green
pStructureColor.Red = 152
pStructureColor.Blue = 0
        pStructureColor.Green = 230

        'create the symbols
        Dim pStructureSymbol As New ESRI.ArcGIS.Display.SimpleMarkerSymbol
       
        'construct the structures symbol
        pStructureSymbol.Style = ESRI.ArcGIS.Display.esriSimpleMarkerStyle.esriSMSCircle
        pStructureSymbol.Size = 4
        pStructureSymbol.Outline = True
        pStructureSymbol.OutlineSize = 1
        pStructureSymbol.OutlineColor = pOutlineColor
        pStructureSymbol.Color = pStructureColor
       
        'define renderers
        Dim pStructureRenderer As New ESRI.ArcGIS.Carto.UniqueValueRenderer
       
        'set the fields used in the renderers - we'll just have one, the 'Active' field
        'set usedefaultsymbol to false so that inactive features 
        'will not draw (i.e., if Active <> 1 or Null)
        'structures renderer
        With pStructureRenderer
            .FieldCount = 1
            .Field(0) = "Active"
            .UseDefaultSymbol = False
            'add "1" to the value list for the renderer - i.e., display "1" values using pStructureSymbol
            .AddValue("1", "Active", pStructureSymbol)
            .Label("1") = "Active"
            'add "<Null>" to the value list for the renderer using the same symbology as "1"
            .AddReferenceValue("<Null>", "1")
            'tell it we're using our own custom style
            .ColorScheme = "Custom"
            'tell it the field type for the 'Active' field is not a string (it's an integer)
            .FieldType(0) = False
        End With       


        Dim pLayer As ESRI.ArcGIS.Carto.ILayer
        Dim pFeatureLayer As ESRI.ArcGIS.Carto.IFeatureLayer2
        Dim pGeoFeatureLayerStructures As ESRI.ArcGIS.Carto.IGeoFeatureLayer
       
        'this makes the layer properties symbology tab show
        'the correct interface.
        Dim pPropertyPage As ESRI.ArcGIS.CartoUI.IRendererPropertyPage
        pPropertyPage = New ESRI.ArcGIS.CartoUI.UniqueValuePropertyPage
       
        Do Until pLayer Is Nothing
            If TypeOf (pLayer) Is ESRI.ArcGIS.Carto.IFeatureLayer2 Then
                pFeatureLayer = pLayer
                If pFeatureLayer.FeatureClass.FindField("Active") > 0 Then 'only set the renderer if there is an 'active' field in the layer
                    Select Case pFeatureLayer.FeatureClass.AliasName
                        Case strStructuresLayerName
                            pGeoFeatureLayerStructures = pFeatureLayer
                            pGeoFeatureLayerStructures.Renderer = pStructureRenderer
                            pGeoFeatureLayerStructures.DisplayField = "Active"
                            pGeoFeatureLayerStructures.RendererPropertyPageClassID = pPropertyPage.ClassID
                    End Select
                End If
                pFeatureLayer = Nothing
            End If
            pLayer = pEnumLayers.Next
        Loop
        My.Document.ActiveView.ContentsChanged()
        My.Document.UpdateContents()      
       
        My.Document.ActiveView.Refresh() 'this does nothing
       
        'This also does nothing:
        'My.Document.ActiveView.PartialRefresh(ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewAll, Nothing, pActiveView.Extent)
       
        'This also does nothing:
        'My.ThisApplication.Display.Invalidate(My.Document.ActiveView.Extent, False, ESRI.ArcGIS.Display.esriScreenCache.esriNoScreenCache)
       
        'this makes the screen go blank:
        'Dim pMaps As ESRI.ArcGIS.Carto.IMaps
'pMaps = My.Document.Maps
'My.Document.ActiveView = My.Document.PageLayout
        'My.Document.ActiveView = pMaps.Item(0)
        'My.Document.ActiveView.Refresh()
       
        'this makes the cursor and the point to be drawn offset by about 4 inches:
        'Dim pActiveView As ESRI.ArcGIS.Carto.IActiveView
        'pActiveView = My.Document.FocusMap
        'pActiveView.Deactivate()
        'pActiveView.Activate(My.ThisApplication.Display.hWnd)
0 Kudos
1 Solution

Accepted Solutions
RebeccaZeckoski
Occasional Contributor
I have come across a rather strange workaround, so I figured I should post in case anyone else has this issue in the future.

As far as I can tell, this issue was occurring because I was trying to refresh the view as part of my OnStartEditing event handling (this seems to be a bug, and I've reported it to the lady I was working with at ESRI support on this issue). In my editor extension, the OnStartup wired the OnStartEditing event handler, and the OnStartEditing event handler tried to create the renderer and refresh the view.

I decided that rather than immediately enabling the capabilities of my extension when the editing session starts, I wanted to have the user click a button to enable the capabilities. I'll skip over all my reasoning on that as it's irrelevant to the issue at hand.

What is relevant is that I moved the call to the rendering routine (CreateRenderer) (with the code as previously posted) OUT of the OnStartEditing event handler and INTO my new button click event. So, the new flow is something like this:

On Startup --> Enable new custom button, Wire OnStartEditing and OnStopEditing

Custom button click --> run CreateRenderer subroutine

And voila! All the sudden my screen actually refreshes. I want to emphasize that I changed NOTHING in the CreateRenderer subroutine - I just moved the call to it out of the OnStartEditing Event and into the new button click event.

If I do hear back from ESRI about this issue I'll post any additional relevant information.

View solution in original post

0 Kudos
6 Replies
KenBuja
MVP Esteemed Contributor
Here's code I'm using in my Editor Extension that will apply a new renderer to a layer and it correctly updates the TOC and map. This extension allows you to create a classification scheme that can be used in point, line, or polygon datasets, so I'm creating a unique value renderer for each type. This way, the color selection will be the same for each dataset it's applied to. I'm storing the renderer information in a dictionary (theDict), which also contains information about all the different of values that are used in the classification scheme. These are stored as numeric keys within the dictionary. This code for the first routine is shown below. The code for CreateRenderer will be in the following post.

However, I am having a problem with another associated script that creates a new feature class and applies the renderer to it. I'm using the same logic as in this script, but it's not updating the TOC.

    Protected Overrides Sub OnClick()

        Dim pCV As ESRI.ArcGIS.ArcMapUI.IContentsView
        Dim pGFLayer As ESRI.ArcGIS.Carto.IGeoFeatureLayer
        Dim pLayer As ESRI.ArcGIS.Carto.ILayer
        Dim pRPPage As ESRI.ArcGIS.CartoUI.IRendererPropertyPage
        Dim pSet As ESRI.ArcGIS.esriSystem.ISet = New ESRI.ArcGIS.esriSystem.Set
        Dim ShapeType As String

        Try
            If Not theDict.ContainsKey("HDX.Point Legend") Then CreateRenderer()

            pCV = My.ArcMap.Document.CurrentContentsView
            If TypeOf pCV.SelectedItem Is ESRI.ArcGIS.Carto.IGeoFeatureLayer Then
                pGFLayer = pCV.SelectedItem
                If pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint Then
                    ShapeType = "Point"
                ElseIf pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline Then
                    ShapeType = "Line"
                ElseIf pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon Then
                    ShapeType = "Polygon"
                Else
                    Exit Sub
                End If
                pGFLayer.Renderer = theDict.Item("HDX." & ShapeType & " Legend")
                pRPPage = New ESRI.ArcGIS.CartoUI.UniqueValuePropertyPage
                pGFLayer.RendererPropertyPageClassID = pRPPage.ClassID
            ElseIf TypeOf pCV.SelectedItem Is ESRI.ArcGIS.esriSystem.ISet Then
                pSet = pCV.SelectedItem
                pLayer = pSet.Next
                Do Until pLayer Is Nothing
                    If TypeOf pLayer Is ESRI.ArcGIS.Carto.IGeoFeatureLayer Then
                        pGFLayer = pLayer
                        If pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint Or pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline Or pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon Then
                            If pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint Then
                                ShapeType = "Point"
                            ElseIf pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline Then
                                ShapeType = "Line"
                            ElseIf pGFLayer.FeatureClass.ShapeType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon Then
                                ShapeType = "Polygon"
                            Else
                                Exit Sub
                            End If
                            pGFLayer.Renderer = theDict.Item("HDX." & ShapeType & " Legend")
                            pRPPage = New ESRI.ArcGIS.CartoUI.UniqueValuePropertyPage
                            pGFLayer.RendererPropertyPageClassID = pRPPage.ClassID
                        End If
                    End If
                    pLayer = pSet.Next
                Loop
            End If

            My.ArcMap.Document.ActiveView.ContentsChanged()
            My.ArcMap.Document.UpdateContents()
            My.ArcMap.Document.ActiveView.Refresh()

        Catch ex As Exception
            System.Windows.Forms.MessageBox.Show(ex.ToString, "Create Legend error")
        End Try
    End Sub

0 Kudos
KenBuja
MVP Esteemed Contributor
    Friend Sub CreateRenderer()

        Dim FieldInfo() As Object
        Dim IsOK As Boolean
        Dim ItemCount As Integer = 0
        Dim ItemList() As Object
        Dim LegendText As String
        Dim pBlack As ESRI.ArcGIS.Display.IRgbColor = New ESRI.ArcGIS.Display.RgbColor
        Dim pLineColorEnum As ESRI.ArcGIS.Display.IEnumColors
        Dim pLineSym As ESRI.ArcGIS.Display.ISimpleLineSymbol = New ESRI.ArcGIS.Display.SimpleLineSymbol
        Dim pLineUVRenderer As ESRI.ArcGIS.Carto.IUniqueValueRenderer = New ESRI.ArcGIS.Carto.UniqueValueRenderer
        Dim pPink As ESRI.ArcGIS.Display.IRgbColor = New ESRI.ArcGIS.Display.RgbColor
        Dim pPointColorEnum As ESRI.ArcGIS.Display.IEnumColors
        Dim pPointSym As ESRI.ArcGIS.Display.ISimpleMarkerSymbol = New ESRI.ArcGIS.Display.SimpleMarkerSymbol
        Dim pPointUVRenderer As ESRI.ArcGIS.Carto.IUniqueValueRenderer = New ESRI.ArcGIS.Carto.UniqueValueRenderer
        Dim pPolygonColorEnum As ESRI.ArcGIS.Display.IEnumColors
        Dim pPolygonOutline As ESRI.ArcGIS.Display.ISimpleLineSymbol = New ESRI.ArcGIS.Display.SimpleLineSymbol
        Dim pPolygonSym As ESRI.ArcGIS.Display.ISimpleFillSymbol = New ESRI.ArcGIS.Display.SimpleFillSymbol
        Dim pPolygonUVRenderer As ESRI.ArcGIS.Carto.IUniqueValueRenderer = New ESRI.ArcGIS.Carto.UniqueValueRenderer
        Dim pRColorRamp As ESRI.ArcGIS.Display.IColorRamp = New ESRI.ArcGIS.Display.RandomColorRamp
        Dim pRed As ESRI.ArcGIS.Display.IRgbColor = New ESRI.ArcGIS.Display.RgbColor

        Try
            For Each Key As Object In theDict.Keys
                If IsNumeric(Key) Then ItemCount += 1
                If CStr(Key) = "HDX.Field0" Then FieldInfo = theDict.Item(Key)
            Next

            pRColorRamp.Size = ItemCount
            pRColorRamp.CreateRamp(IsOK)
            If Not IsOK Then
                System.Windows.Forms.MessageBox.Show("There was a  problem in creating the legends for this scheme.", "No legends created",  Windows.Forms.MessageBoxButtons.OK,  Windows.Forms.MessageBoxIcon.Warning)
                Exit Sub
            End If

            pPointColorEnum = pRColorRamp.Colors
            pLineColorEnum = pRColorRamp.Colors
            pPolygonColorEnum = pRColorRamp.Colors

            pBlack.RGB = RGB(0, 0, 0)
            pRed.RGB = RGB(255, 0, 0)
            pPink.RGB = RGB(255, 190, 232)

            pPointSym.Color = pRed
            pPointSym.Size = 6
            pPointSym.Style = ESRI.ArcGIS.Display.esriSimpleMarkerStyle.esriSMSX
            With pPointUVRenderer
                .FieldCount = 1
                .Field(0) = FieldInfo(1)
                .DefaultLabel = "Incorrectly classified"
                .DefaultSymbol = pPointSym
                .UseDefaultSymbol = True
            End With

            pLineSym.Color = pRed
            pLineSym.Width = 2
            pLineSym.Style = ESRI.ArcGIS.Display.esriSimpleLineStyle.esriSLSDash
            With pLineUVRenderer
                .FieldCount = 1
                .Field(0) = FieldInfo(1)
                .DefaultLabel = "Incorrectly classified"
                .DefaultSymbol = pLineSym
                .UseDefaultSymbol = True
            End With

            pPolygonOutline.Color = pRed
            pPolygonOutline.Width = 2
            pPolygonSym.Color = pPink
            pPolygonSym.Outline = pPolygonOutline
            With pPolygonUVRenderer
                .FieldCount = 1
                .Field(0) = FieldInfo(1)
                .DefaultLabel = "Incorrectly classified"
                .DefaultSymbol = pPolygonSym
                .UseDefaultSymbol = True
            End With

            For Each Key As Object In theDict.Keys
                If IsNumeric(Key) Then
                    pPointSym = New ESRI.ArcGIS.Display.SimpleMarkerSymbol
                    pPointSym.Color = pPointColorEnum.Next
                    pPointSym.Size = 6
                    pPointSym.Style = ESRI.ArcGIS.Display.esriSimpleMarkerStyle.esriSMSCircle

                    pLineSym = New ESRI.ArcGIS.Display.SimpleLineSymbol
                    pLineSym.Color = pLineColorEnum.Next
                    pLineSym.Width = 0.4

                    pPolygonSym = New ESRI.ArcGIS.Display.SimpleFillSymbol
                    pPolygonOutline = New ESRI.ArcGIS.Display.SimpleLineSymbol
                    pPolygonSym.Color = pPolygonColorEnum.Next
                    pPolygonOutline.Color = pBlack
                    pPolygonOutline.Width = 0.4
                    pPolygonSym.Outline = pPolygonOutline

                    ItemList = theDict.Item(Key)
                    LegendText = ""
                    For i As Integer = 1 To ItemList.GetUpperBound(0)
                        LegendText = LegendText & ItemList(i) & " | "
                    Next
                    LegendText = Left(LegendText, Len(LegendText) - 3)

                    With pPointUVRenderer
                        .AddValue(Key, "Description", pPointSym)
                        .Label(Key) = LegendText
                        .Symbol(Key) = pPointSym
                    End With

                    With pLineUVRenderer
                        .AddValue(Key, "Description", pLineSym)
                        .Label(Key) = LegendText
                        .Symbol(Key) = pLineSym
                    End With

                    With pPolygonUVRenderer
                        .AddValue(Key, "Description", pPolygonSym)
                        .Label(Key) = LegendText
                        .Symbol(Key) = pPolygonSym
                    End With
                End If
            Next

            If theDict.ContainsKey("HDX.Point Legend") Then theDict.Remove("HDX.Point Legend")
            theDict.Add("HDX.Point Legend", pPointUVRenderer)
            If theDict.ContainsKey("HDX.Line Legend") Then theDict.Remove("HDX.Line Legend")
            theDict.Add("HDX.Line Legend", pLineUVRenderer)
            If theDict.ContainsKey("HDX.Polygon Legend") Then theDict.Remove("HDX.Polygon Legend")
            theDict.Add("HDX.Polygon Legend", pPolygonUVRenderer)

        Catch ex As Exception
            System.Windows.Forms.MessageBox.Show(ex.ToString, "CreateRenderer")
        End Try

    End Sub
0 Kudos
RebeccaZeckoski
Occasional Contributor
Thanks for your post, but in essence you seem to be taking the same steps I take, though your renderer definition is more complicated.  This just further confuses me as to why my code isn't working!
0 Kudos
RebeccaZeckoski
Occasional Contributor
I have come across a rather strange workaround, so I figured I should post in case anyone else has this issue in the future.

As far as I can tell, this issue was occurring because I was trying to refresh the view as part of my OnStartEditing event handling (this seems to be a bug, and I've reported it to the lady I was working with at ESRI support on this issue). In my editor extension, the OnStartup wired the OnStartEditing event handler, and the OnStartEditing event handler tried to create the renderer and refresh the view.

I decided that rather than immediately enabling the capabilities of my extension when the editing session starts, I wanted to have the user click a button to enable the capabilities. I'll skip over all my reasoning on that as it's irrelevant to the issue at hand.

What is relevant is that I moved the call to the rendering routine (CreateRenderer) (with the code as previously posted) OUT of the OnStartEditing event handler and INTO my new button click event. So, the new flow is something like this:

On Startup --> Enable new custom button, Wire OnStartEditing and OnStopEditing

Custom button click --> run CreateRenderer subroutine

And voila! All the sudden my screen actually refreshes. I want to emphasize that I changed NOTHING in the CreateRenderer subroutine - I just moved the call to it out of the OnStartEditing Event and into the new button click event.

If I do hear back from ESRI about this issue I'll post any additional relevant information.
0 Kudos
RebeccaZeckoski
Occasional Contributor
ESRI support has confirmed that I have found a bug in ArcGIS 10 and has submitted a bug report for it (bug NIM080497). The specific bug is that IActiveView::Refresh does not work when called inside an IEditEvents.OnStartEditing event handler. They didn't mention when this might be fixed.
0 Kudos
KenBuja
MVP Esteemed Contributor
By the way, I was able to solve my problem with the view not refreshing after applying a renderer. In my case, I had a routine to create a new featureclass and apply a renderer, but new layer wouldn't get the renderer applied to it. I had a separate routine to just apply a renderer to a selected layer, which did work properly. So I ended up just calling that separate routine at the end of the create new featureclass routine and the renderer was applied as expected. Maybe it's a related bug.
0 Kudos