The FrameworkElement.FindName(string name)
method returns an object from the XAML namescope. As a reverse to this, is there a way to get the name of the object as a string by passing the object?
Example:
The following ViewPort3D contains a red cone and a blue cone. On hit-testing I can get the cone object that was clicked on. But what I need is information on which cone was hit (preferably "redCone" as a string), so I can use this information to decide, say, which image to popup
<Viewport3D Name="myViewport" MouseDown="myViewport_MouseDown">
<Viewport3D.Children>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup >
<Model3DGroup.Children>
<!-- Define a red cone -->
<GeometryModel3D x:Name="redCone">
<GeometryModel3D.Geometry>
<MeshGeometry3D />
</GeometryModel3D.Geometry>
</GeometryModel3D>
<!-- Define a blue cone -->
<GeometryModel3D x:Name="redCone">
<GeometryModel3D.Geometry>
<MeshGeometry3D />
</GeometryModel3D.Geometry>
</GeometryModel3D>
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
What I have so far:
I do have a non-dynamic solution where I have to check the object that was clicked on against hard-coded objects:
private void myViewport_MouseDown(object sender, MouseButtonEventArgs e)
{
Point mousePoint = e.GetPosition(this);
PointHitTestParameters pointparams = new PointHitTestParameters(mousePoint);
//Test for a result in the Viewport3D
VisualTreeHelper.HitTest(myViewport, null, HTResult, pointparams);
}
public HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult rawresult)
{
RayHitTestResult rayResult = rawresult as RayHitTestResult;
if (rayResult != null)
{
RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult;
if (rayMeshResult != null)
{
GeometryModel3D hitGeometry = rayMeshResult.ModelHit as GeometryModel3D;
// Non-dynamic solution:
if (hitGeometry.Equals(redCone))
infoImage.Source = System.IO.Path.Combine(imagesPath, "redCone.png");
else if (hitGeometry.Equals(blueCone))
infoImage.Source = System.IO.Path.Combine(imagesPath, "blueCone.png");
// Desired solution:
// string hitName = FindObject(hitGeometry);
// infoImage.Source = System.IO.Path.Combine(imagesPath, hitName, ".png");
}
}
return HitTestResultBehavior.Stop;
}
But as you can see, I have to write code for each GeometryModel3D
object I want to hit-test against and compare it with hitGeometry
. It would be nice to have a method (like FindObject
in the code above) that returns the name assigned to 'hitGeometry` in XAML namescope by passing the object.
The question:
Is there a solution where I can get the name of object that was hit so I don't have to go change my code every time the 3D landscape changes?
Things to note:
- This is for
GeometryModel3D
objects so there is noName
property. GeometryModel3D
is a sealed class- The actual XAML for the ViewPort3D is generated from .3ds files and is more complicated than this so I cannot afford to change the structure