Select to view content in your preferred language

FlareClusterer : how to get the graphic clicked

2018
12
01-30-2011 11:23 PM
chitrasrivastava
Emerging Contributor
Hi,

I have implemented FlareClusterer and I have a requirement in my project that if i click on the individual flare I should be able to find out which object has been clicked.

graphicsLayer.FindGraphicsInHostCoordinates(transformScreenPnt) is not giving me the correct object which has been selected.
From the given collection of objects in flare cluster symbol , i want to identify which one is clicked.


Regards,
Chitra
0 Kudos
12 Replies
JenniferNery
Esri Regular Contributor
You have tried this workaround but it did not work? http://forums.arcgis.com/threads/18534-FlareClusterer-event-bug
0 Kudos
KyleBunting
Emerging Contributor
I am having the same issue and FindGraphicsInHostCoordinates does not work.  I need to be able to identify the individual symbol clicked in the flare, and FindGraphicsInHostCoordinates returns all the Graphic objects within the cluster.  Is there a way to distinguish which one was actually clicked?
0 Kudos
dotMorten_esri
Esri Notable Contributor
At this point in time, you access the cluster graphic that represents group of features, and not the individual graphic that one of the "flares" represents. If the user needs to interact with the individual features, they will need to zoom into a level where they spread out to individual symbols.
This is by design, but we are considering options for handling this use case in a future release.
0 Kudos
chitrasrivastava
Emerging Contributor
Hi,

This is our functional requirement that we should be able to access the attributes of individual objects behind the clusterer.

I hope to get to know about the resolution of this issue soon.

Regards,
Chitra
0 Kudos
KyleBunting
Emerging Contributor
This is a functional requirement for my application as well.  I have cases where it is not possible to zoom down in order to separate the individual items in a cluster into separate graphics.  I am currently handling this by displaying a window panel with a list of the items at a given location, and allowing the user to select which item they want from the list.  However, when a user can mouse over the "flares" and get information about a specific item, it doesn't make the most sense for them to have to "reselect" the item in a list after clicking on it.

Would it be possible to capture the click event in an overridden GraphicsCluster class?  If so, could someone please provide a sample of how to go about doing that?
0 Kudos
KyleBunting
Emerging Contributor
I have been unable to get any custom click events to work in a custom Clusterer class.  However, I was able to work around this problem by creating a CustomClusterer class that inherits from FlareClusterer.  Wihtin the overridden OnCreateGraphic method I looped through the GraphicCollection passed into the clusterer and assigned an ElementIndex attribute to each graphic in the collection.  The ElementIndex must start at 0, and increment by one for each element in the clusterer.

Clicking on one of the "flares" of a clusterer can then be handled using the Map_MouseLeftButtonDown.  The "flares" are represented by System.Windows.Shapes.Ellipse objects, which are named "elm0," "elm1," "elm2," etc.  The e.OriginalSource object can be cast to a System.Windows.Shapes.Ellipse object, and its name can them be compared to "elm" + the ElementIndex attribute of each Graphic item in the collection returned using GraphicsLayer.FindGraphicsInHostCoordinates().
0 Kudos
chitrasrivastava
Emerging Contributor
Hi Kyle,

Even I had tried the custom event handling but it didn't work in the expected way.
Now I am capturing the flare graphics click event in map left button down and trying to get the graphics objects by findgraphicsinhostcoordinate method. This way I am able to

I have some other stuff also which requires overriding oncreate graphics of flare clusture.
Can you share your code for that , it might help me.

I guess you have already done that..Can you please share the code.

Regards,
Chitra
0 Kudos
KyleBunting
Emerging Contributor
Chitra,

The code for my custom FlareClusterer class is below, as well a snippet of the code from my Map_MouseLeftButtonDown event handler.  To provide a bit of background on what I am doing in my project, I have a world map to which I am adding graphics that represent each member of the organization for which I work.  My goal was to be able to click on any of the "dots" on the map and from there display either a list of all the people at that location or if a single "dot" was clicked, then display the personal information for the person clicked.

Currently, I do not have a need to do any further manipulation of the FlareClusterer, so my CustomFlareClusterer is very simple, and is only used to add my "ElementIndex" attribute to each Graphic object.

CustomFlareClusterer.cs
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;

namespace MySilverlightProject.Controls
{
 public class CustomFlareClusterer : FlareClusterer
 {
  protected override Graphic OnCreateGraphic(GraphicCollection cluster, MapPoint point, int maxClusterCount)
  {
   int elementIndex = 0;
   
   // Loop through the Graphics in the cluster, and add an ElementIndex attribute to each item
   foreach (Graphic g in cluster)
   {
    // First, check to see if the Graphic object already contains the ElementIndex attribute, and reset it if necessary.
    // This is necessary to handle cases where the Graphic object was part of a large collection of Graphics prior to 
    // the user zooming in to get to the Flare Clusterer object on the map.
    if (g.Attributes.ContainsKey("ElementIndex"))
     g.Attributes["ElementIndex"] = elementIndex;
    else
     g.Attributes.Add("ElementIndex", elementIndex);
     
    elementIndex++;
   }
   
   // Now pass our modified GraphicCollection object, "cluster," into the GraphicClusterer OnCreateGraphic method
   return base.OnCreateGraphic(cluster, point, maxClusterCount);
  }
 }
}


To handle the click event of any Graphics on the map, I have wrapped everything into the Map_MouseLeftButtonDown event handler.  This allows me to avoid having to handle Graphics in a Clusterer separately from stand-alone Graphics.  I've left a lot of my code out of the snippet below, but you should be able to discern how I am using the ElementIndex attribute on each Graphic object to figure out which element of a flare was clicked.

Map_MouseLeftButtonDown event handler
private void Map_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
 // Attempt to case the clicked object to an Ellipse object
 Ellipse ellipse = e.OriginalSource as Ellipse;
 
 // Get a reference to the map's GraphicsLayer
 GraphicsLayer graphicsLayer = Map.Layers["DynamicGraphicsLayer"] as GraphicsLayer;
 GeneralTransform generalTransform = Map.TransformToVisual(Application.Current.RootVisual);
 System.Windows.Point transformScreenPnt = generalTransform.Transform(e.GetPosition(this.Map));
 var graphics = graphicsLayer.FindGraphicsInHostCoordinates(transformScreenPnt);

 foreach (Graphic g in graphics)
 {
  // If the Graphic object clicked by the user is not part of a cluster...
  if (graphics.Count<Graphic>() == 1)
  {
   // Add processing code here.  What I do is navigate to another page, and pass in the associated Id Attribute of the
   // Graphic object that was clicked.
   
   // Exit
   break;
  }
  
  // Check to see if the object clicked by the user was actually an Ellipse object.  The object will be an ellipse if 
  // the user clicked on one of the "flares," but that may or may not be the case if they clicked on the center Graphic
  // of a cluster, or if they click on a cluster that contains too many objects to be a FlareClusterer.
  if (ellipse != null)
  {
   if (ellipse.Name.ToLower() == "mainsymbol")
   {
    // The Ellipse that represents the center of a cluster was clicked, so what I do here is create a list of 
    // the "Ids" for each Graphic in cluster.  The Id is pulled from the Attributes.
    
    // Add processing code here.  I display a panel on the side of the map with a list of people at the location clicked.
   }
   else if (ellipse.Name.ToLower().StartsWith("elm"))
   {
    // Each "flare" in a cluster is an Ellipse with a name that is "elm" + an index starting from the right-hand side
    // and going around clockwise.  The first "flare" will be named "elm0," the second "elm1," and so on.  Using that
    // information, we can match our ElementIndex up with the element clicked to figure out which "flare" within the 
    // cluster was clicked.  All we need to do is prepend "elm" to our ElementIndex and compare it the name of the
    // Ellipse that was clicked.
    if ((g.Attributes.ContainsKey("ElementIndex")) && ("elm" + g.Attributes["ElementIndex"].ToString() == ellipse.Name))
    {
     // Add processing code here.  What I do is navigate to another page, and pass in the associated Id Attribute of the
     // Graphic object that was clicked.
     
     // Exit, since we've found what we were looking for.
     break;
    }
   }
   else
   {
    // Add processing code here.  I display a panel on the side of the map with a list of people at the location clicked.
   }
  }
  else
  {
   // This should be used to handle the cases where the user clicked on a GraphicClusterer, but the actual click event
   // was fired for a child of the Ellipse object, such as the text containing the number of items in the cluster.
   
   // Add processing code here.  I display a panel on the side of the map with a list of people at the location clicked.
  }
 }
}


Hope this helps.

Cheers,
Kyle
0 Kudos
Charles__Jamie_Phillips
Occasional Contributor
So basically you want a maptip for each flare?  Is this correct?

We did something similiar where we created a custom maptip that worked with the flare cluster.  When you hover over the cluster it give you a datagrid will all the data in it.  Let me know if that may meet your needs.
0 Kudos