Select to view content in your preferred language

Really slow with lots (1500) custom MarkerSymbols, but not with SimpleMarkerSymbols

1480
11
07-30-2010 01:54 PM
MartenLiebster
Deactivated User
I've got an app which uses a custom MarkerSymbol defined within the XAML of the UserControl.

The symbol has an ellipse to mark the point on the map and canvas with about 8 textblocks and 3 buttons. I've got 2 VisualStates defined for MouseOver and MouseIn. It's default state is just to show the ellipse, and when mouse enters, the canvas is displayed with ScaleTransforms. When the mouse leaves, it reverts back to it's default state.

There's databinding using the ESRI DictionaryConverter going on as well for some of the textblocks and 1 of the button's text.

To display this symbol, I do a database query via WCF RIA. When looping through these results, I essentially do this process:

1) creating a Graphic()
2) populate the Attribute collection
3) assigning the custom symbol to the Symbol
4) add to the Map.Layer.Graphics collection.

Here's a few snippets of the code:

_viewModel.Locations
    .ToList()
    .ForEach(rl => processDataPoint(rl));      


void processDataPoint(Info MapInfo) 
{
    Graphic gr = new Graphic()
            {
                Geometry = new MapPoint(MapInfo.Lon, MapInfo.Lat)
            };
   gr.Attributes.Add("ButtonText", MapInfo.ButtonText);
   gr.Attributes.Add("EllipseFill", MapInfo.EllipseFill);

   // add some more attributes

   gr.Symbol = MyMarkerSymbol; // defined on this UserControl's XAML
   _mapLayer.Graphics.Add(gr);
}


One of my queries returns 1500 results, and perform the above, the map is really really slow.

As a test, I changed the custom symbol out with a SimpleMarkerSymbol and the map is quick and responsive.

So it's something that I am doing...

Is it the VisualStateManager?

Thanks for any help.
0 Kudos
11 Replies
DominiqueBroux
Esri Frequent Contributor
Could you share the XAML of your custom marker symbol?
Which ESRI SL version are you using?
0 Kudos
MartenLiebster
Deactivated User
We're using the new 2.0 version.

The markup is too long to fit into a single, so I split it up.
            <esriSymbols:MarkerSymbol x:Name="LocationMarkerSymbol">
                <esriSymbols:MarkerSymbol.ControlTemplate>
                    <ControlTemplate>
                        <Grid>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="MouseStates">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition GeneratedDuration="00:00:00.25" />
                                    </VisualStateGroup.Transitions>
                                    <VisualState x:Name="MouseOver">
                                        <Storyboard>
                                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                           Duration="00:00:00.25000"
                                                                           Storyboard.TargetName="canvas"
                                                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                                                <EasingDoubleKeyFrame KeyTime="00:00:00"
                                                                      Value="1">
                                                    <EasingDoubleKeyFrame.EasingFunction>
                                                        <QuarticEase EasingMode="EaseIn" />
                                                    </EasingDoubleKeyFrame.EasingFunction>
                                                </EasingDoubleKeyFrame>
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                           Duration="00:00:00.25000"
                                                                           Storyboard.TargetName="canvas"
                                                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
                                                <EasingDoubleKeyFrame KeyTime="00:00:00"
                                                                      Value="1">
                                                    <EasingDoubleKeyFrame.EasingFunction>
                                                        <QuarticEase EasingMode="EaseIn" />
                                                    </EasingDoubleKeyFrame.EasingFunction>
                                                </EasingDoubleKeyFrame>
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Normal" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Canvas x:Name="canvas"
                                    Margin="0,0,0,-69"
                                    Width="250"
                                    RenderTransformOrigin="0,0">
                                <Canvas.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform ScaleX="0"
                                                        ScaleY="0" />
                                        <SkewTransform AngleX="0" />
                                        <RotateTransform />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </Canvas.RenderTransform>
                                <Rectangle StrokeThickness="0"
                                           RadiusX="10"
                                           RadiusY="10"
                                           Height="159"
                                           Width="250"
                                           Opacity="0.85">
                                    <Rectangle.Fill>
                                        <LinearGradientBrush EndPoint="0.5,1"
                                                             StartPoint="0.5,0">
                                            <GradientStop Color="#FF929292"
                                                          Offset="1" />
                                            <GradientStop Color="White" />
                                        </LinearGradientBrush>
                                    </Rectangle.Fill>
                                </Rectangle>
                                <TextBlock x:Name="txtType"
                                           Height="20"
                                           Canvas.Left="8"
                                           Canvas.Top="8"
                                           Text="Type"
                                           TextWrapping="Wrap"
                                           RenderTransformOrigin="0.5,0.5">
                 <TextBlock.RenderTransform>
                  <TransformGroup>
                   <ScaleTransform />
                   <SkewTransform />
                   <RotateTransform />
                   <TranslateTransform />
                  </TransformGroup>
                 </TextBlock.RenderTransform>
                                </TextBlock>
                                <TextBlock x:Name="txtAddress"
                                           Height="20"
                                           Canvas.Left="7"
                                           Canvas.Top="53"
                                           Text="Address"
                                           TextWrapping="Wrap"
                                           RenderTransformOrigin="0.5,0.5">
                 <TextBlock.RenderTransform>
                  <TransformGroup>
                   <ScaleTransform />
                   <SkewTransform />
                   <RotateTransform />
                   <TranslateTransform />
                  </TransformGroup>
                 </TextBlock.RenderTransform>
                                </TextBlock>
                                <TextBlock x:Name="txtName"
                                           Height="20"
                                           Canvas.Left="8"
                                           Canvas.Top="33"
                                           Text="Name"
                                           TextWrapping="Wrap"
                                           RenderTransformOrigin="0.5,0.5">
                 <TextBlock.RenderTransform>
                  <TransformGroup>
                   <ScaleTransform />
                   <SkewTransform />
                   <RotateTransform />
                   <TranslateTransform />
                  </TransformGroup>
                 </TextBlock.RenderTransform>
                                </TextBlock>
                                <Button Height="24"
                                        Width="101"
                                        Content="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=ButtonText, Mode=OneWay}"
                                        Click="btnContactLocation_Click"
                                        x:Name="btnContactLocation"
                                        Canvas.Left="141"
                                        Canvas.Top="8"
                                        Style="{StaticResource voloButton3}" />
                                <Button Height="24"
                                        Width="72"
                                        Content="Zoom"
                                        x:Name="btnZoom"
                                        Click="btnZoom_Click"
                                        Canvas.Left="170"
                                        Canvas.Top="98"
                                        Style="{StaticResource voloButton3}" />
                                <TextBlock x:Name="lblType"
                                           Height="20"
                                           Canvas.Left="63"
                                           Canvas.Top="8"
                                           TextWrapping="Wrap"
                                           Text="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=Type, Mode=OneWay}"
                                           RenderTransformOrigin="0.5,0.5">
                 <TextBlock.RenderTransform>
                  <TransformGroup>
                   <ScaleTransform />
                   <SkewTransform />
                   <RotateTransform />
                   <TranslateTransform />
                  </TransformGroup>
                 </TextBlock.RenderTransform>
                                </TextBlock>
0 Kudos
MartenLiebster
Deactivated User
Here's the second part of the symbol.
                                <TextBlock x:Name="lblName"
                                           Height="20"
                                           Canvas.Left="63"
                                           Canvas.Top="33"
                                           TextWrapping="Wrap"
                                           Text="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=Name, Mode=OneWay}"
                                           RenderTransformOrigin="0.5,0.5">
                 <TextBlock.RenderTransform>
                  <TransformGroup>
                   <ScaleTransform />
                   <SkewTransform />
                   <RotateTransform />
                   <TranslateTransform />
                  </TransformGroup>
                 </TextBlock.RenderTransform>
                                </TextBlock>
                                <TextBlock x:Name="lblAddress"
                                           Height="20"
                                           Canvas.Left="63"
                                           Canvas.Top="53"
                                           TextWrapping="Wrap"
                                           Text="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=Address, Mode=OneWay}"
                                           RenderTransformOrigin="0.5,0.5">
                 <TextBlock.RenderTransform>
                  <TransformGroup>
                   <ScaleTransform />
                   <SkewTransform />
                   <RotateTransform />
                   <TranslateTransform />
                  </TransformGroup>
                 </TextBlock.RenderTransform>
                                </TextBlock>
                                <StackPanel Height="20"
                                            Width="222"
                                            Canvas.Left="28"
                                            Canvas.Top="73"
                                            Orientation="Horizontal">
                                    <TextBlock x:Name="lblCity"
                                               Height="20"
                                               TextWrapping="Wrap"
                                               Text="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=City, Mode=OneWay}"
                                               RenderTransformOrigin="0.5,0.5"
                                               HorizontalAlignment="Left">
                  <TextBlock.RenderTransform>
                   <TransformGroup>
                    <ScaleTransform />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                   </TransformGroup>
                  </TextBlock.RenderTransform>
                                    </TextBlock>
                                    <TextBlock x:Name="lblState"
                                               Height="20"
                                               TextWrapping="Wrap"
                                               Text="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=State, Mode=OneWay}"
                                               RenderTransformOrigin="0.5,0.5"
                                               HorizontalAlignment="Left"
                                               Margin="5,0,0,0">
                  <TextBlock.RenderTransform>
                   <TransformGroup>
                    <ScaleTransform />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                   </TransformGroup>
                  </TextBlock.RenderTransform>
                                    </TextBlock>
                                    <TextBlock x:Name="lblZip"
                                               Height="20"
                                               TextWrapping="Wrap"
                                               RenderTransformOrigin="0.5,0.5"
                                               Text="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=Zip, Mode=OneWay}"
                                               HorizontalAlignment="Left"
                                               Margin="5,0,0,0">
                  <TextBlock.RenderTransform>
                   <TransformGroup>
                    <ScaleTransform />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                   </TransformGroup>
                  </TextBlock.RenderTransform>
                                    </TextBlock>
                                </StackPanel>
                                <Button Height="24"
                                        Width="156"
                                        Content="Show Location Records"
                                        x:Name="btnLoadRecords"
                                        Click="btnLoadRecords_Click"
                                        Canvas.Left="49"
                                        Canvas.Top="126"
                                        Style="{StaticResource voloButton3}" />
                            </Canvas>
                            <Ellipse Fill="{Binding Attributes, Converter={StaticResource DictionaryConverter}, ConverterParameter=EllipseFill, Mode=OneWay}"
                                     Height="10"
                                     HorizontalAlignment="Left"
                                     Margin="-5,-5,0,0"
                                     VerticalAlignment="Top"
                                     Width="10" />
                            <Path Stretch="Fill"
                                  Height="4.439"
                                  HorizontalAlignment="Left"
                                  Margin="-4.875,-5.001,0,0"
                                  VerticalAlignment="Top"
                                  Width="9.833"
                                  UseLayoutRounding="False"
                                  Data="M-4.875,-1.1041666 L-4.6874614,-1.7347159 L-4.4217825,-2.3129232 L-4.2498722,-2.6254678 L-4.0154495,-2.9380124 L-3.7966547,-3.2349296 L-3.5778599,-3.5005925 L-3.3039556,-3.7723901 L-2.8277068,-4.1256814 L-2.4995148,-4.3288355 L-2.192811,-4.4872231 L-1.8389189,-4.6330986 L-1.5149387,-4.7820249 L-1.2203623,-4.8680453 L-0.79080993,-4.9610057 L-0.39710262,-5.0018063 L0.032252222,-5.0011506 L0.48546976,-4.9542656 L0.93683147,-4.8971167 L1.2199948,-4.8448663 L1.45706,-4.7929196 L1.7044687,-4.7195158 L1.9993337,-4.6053643 L2.2701409,-4.4803271 L2.5952756,-4.3132081 L2.8557456,-4.126091 L3.10321,-3.9385011 L3.2908576,-3.7717853 L3.4860826,-3.609983 L3.7248838,-3.3674874 L3.9080436,-3.1255391 L4.1112103,-2.8598762 L4.2831202,-2.6254678 L4.501915,-2.2191598 L4.7299762,-1.7503567 L4.8134851,-1.4794436 L4.8556581,-1.2085304 L4.918335,-0.97929627 L4.9596744,-0.77107668 L4.9600081,-0.56217402 L4.5432706,-0.85394824 L4.314065,-1.0831994 L3.9806747,-1.3332915 L3.5222633,-1.5625427 L2.9805043,-1.8126348 L2.2095397,-2.021045 L1.5635965,-2.1252501 L0.68844742,-2.229455 L-0.37423354,-2.187773 L-1.4785882,-2.0835679 L-2.3179469,-1.9737235 L-3.5622764,-1.6042247 L-4.0415249,-1.3749735 L-4.3957515,-1.1457224 z">
                                <Path.Fill>
                                    <LinearGradientBrush EndPoint="0.5,1"
                                                         StartPoint="0.5,0">
                                        <GradientStop Color="#3FFFF9F9"
                                                      Offset="1" />
                                        <GradientStop Color="White" />
                                    </LinearGradientBrush>
                                </Path.Fill>
                            </Path>
                        </Grid>
                    </ControlTemplate>
                </esriSymbols:MarkerSymbol.ControlTemplate>
            </esriSymbols:MarkerSymbol>
0 Kudos
DominiqueBroux
Esri Frequent Contributor
You could try to set the 'canvas' to 'Collapsed' in the symbol definition and to make it visible in the animation when the mouse is over.

This should avoid the framework to render all these big canvas (even if the scale is null, likely the framework try to render it as it's visible).
0 Kudos
MartenLiebster
Deactivated User
You could try to set the 'canvas' to 'Collapsed' in the symbol definition and to make it visible in the animation when the mouse is over.

This should avoid the framework to render all these big canvas (even if the scale is null, likely the framework try to render it as it's visible).


Thanks

I will give it a try!

Would it help if I set the IsHitTestVisible="False" on the items that don't have interaction?
0 Kudos
MartenLiebster
Deactivated User
It's better, but still very much choppy when panning the map.

My computer is about 2 years old, so it should be up to the task. I more concerned about our customers who may be running older & slower systems.

In my storyboard I added this:
    <VisualState x:Name="MouseOver">
        <Storyboard>
             <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                                           Storyboard.TargetName="canvas">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>


And for my canvas
<Canvas x:Name="canvas"
                                    Height="125"
                                    Margin="0"
                                    Width="250"
                                    Visibility="Collapsed"
                                    RenderTransformOrigin="0,0">
0 Kudos
MartenLiebster
Deactivated User
I've been trying various things - a possible solution may be to keep my original code intact, plus the initial change to collapsed, but add a FlareCluster to my layer with all the locations.

We still would prefer the look and feel of the original.

Thanks
0 Kudos
AliMirzabeigi
Emerging Contributor
Have you tried to use FeatureLayer instead? You can enable FeatureLayer's OnDemand mode to limit number of features being retrieved from your server at each extent of your map control. Optionally, you can also set its OnDemandCacheSize property to a value that is appropriate for your data source. BTW, the more complex your map symbologies, the slower your map rendering.
0 Kudos
MartenLiebster
Deactivated User
Have you tried to use FeatureLayer instead? You can enable FeatureLayer's OnDemand mode to limit number of features being retrieved from your server at each extent of your map control. Optionally, you can also set its OnDemandCacheSize property to a value that is appropriate for your data source. BTW, the more complex your map symbologies, the slower your map rendering.


Thanks for the response.

I will look into it, but I'm not sure how to connect the FeatureLayer to my ViewModel/WCF RIA service that is the source.

Aren't feature layers based on the ArcGIS engine on the server using spatial queries?

Additionally the default extent is entire US, so the initial server load would entail all of them loaded at one time.
0 Kudos