How can I access x:Name attribute for model returned by HitTest?
I have a GeometryModel3D identified by an x:Name like this:
<GeometryModel3D x:Name="surface1" Geometry="{StaticResource terrain}"
Material="{StaticResource terrainNone}">
Is there a way to determine the x:Name value of this GeometryModel3D in the code behind? I would like to find out which model and mesh is returned from the HitTest.
void MouseDownHandler(object sender, MouseButtonEventArgs args)
{
Viewport3D viewport = (Viewport3D)sender;
Point location = args.GetPosition(viewport);
HitTestResult result = VisualTreeHelper.HitTest(viewport, location);
if (result != null && result.VisualHit is ModelVisual3D)
{
RayMeshGeometry3DHitTestResult result3D = result as RayMeshGeometry3DHitTestResult;
GeometryModel3D model = result3D.ModelHit as GeometryModel3D;
MessageBox.Show("model=" + model);
MeshGeometry3D mesh = result3D.MeshHit;
MessageBox.Show("mesh=" + mesh);
}
}
Since GeometryModel3D does not have a Name property, the value assigned to it's x:Name is not programmatically discoverable. Only for elements with a Name property (a la RuntimeNamePropertyAttribute) is x:Name used to assign an object a name. In your situation, x:Name is providing a field name for the GeometryModel3D instance, which is included in the auto-generated class (i.e. the result of your XAML being compiled).
For more info about this, see here: http://msdn2.microsoft.com/en-us/library/ms752290.aspx
Hi Josh,
Thanks, I was hoping there was a way to identify the mesh or model more directly without resorting to one of the methods outlined in http://dotnetaddict.dotnetdevelopersjournal.com/3dhittesting.htm or http://www.dmu.com/avalon3D/a3d10.html
The first creates a lookup dictionary with the GeometryModel3D used as the key and its identifier as a string.
private Dictionary<GeometryModel3D, string> meshes = new Dictionary<GeometryModel3D,string>();
This approach would require creating the GeometryModel3D on the page load and entering each surface into the dictionary. Since my building models are translation from DXF or KMZ it might be possible to run the translation on the fly in the xbap client, but I think performance would be slow.
The second approach compares geometries of the hit result with the resource geometry identified by its x:Key:
RayMeshGeometry3DHitTestResult result3D = result as RayMeshGeometry3DHitTestResult;
GeometryModel3D model = result3D.ModelHit as GeometryModel3D;
if (model.Geometry == Resources["terrain"]){
MessageBox.Show("terrain mesh hit!" );
}
I ran a quick test of the latter approach and it does seem to work with resource declared Geometry. This could work if I modify the DXF/KMZ translation a bit to create all surface geometries as resources with identifers as x:Keys
So in summary the GeometryModel3D returned by the hit test can't be tagged explicitly with additional information but can be identified by either :
A) added to a collection with a GeometryModel3D key and additional text as its associated value as long as you create the GeometryModel3D in code.
B) declare the associated geometry in a resource identified with an x:Key
Well, that is unfortunate ...
The resources comparison is an interesting workaround, might be something worth promoting into the official SDK documentation.
Something else that is interesting is that technically the namescope of the page and its ability to FindName is operative, it's just that "core" classes like GeometryModel3D don't surface the namescopes with APIs.
This suggests another possible workaround, although it is of limited use.
What you can do is call FindName on a parent element such as the Viewport3D. This actually will return an object. That object can be cast and compared to your hit test result. So, if you have a fairly finite number of geometries/models etc. within any given viewport that could be hit, you can have them all available as objects from FindName and try a compare against each.