在.NET 3.5之前,如果想让3D对象响应鼠标事件,通常会在Viewport3D上使用MouseDown事件并进行一些碰撞检测。虽然这种方法可行,但.NET 3.5引入了ModelUIElement3D,这是一个全新的元素,它不仅支持事件,还能让3D对象更加互动。此外,还有一个容器元素ContainerUIElement3D,可以容纳一个或多个ModelUIElement3D元素。
以下是一个简单的示例,展示了如何创建一个3D立方体,并为其添加鼠标点击事件处理程序。
<Window x:Class="Shapes.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Shapes"
Title="Window1" Height="610.122" Width="633.46">
<Window.Resources>
<!-- 3D 立方体 -->
<MeshGeometry3D x:Key="CubeMesh" TriangleIndices="0,1,2 2,3,0 4,7,6 6,5,4 8,11,10 10,9,8 12,13,14 14,15,12 16,17,18 18,19,16 20,23,22 22,21,20" Positions="-1,-1,1 -1,-1,-1 1,-1,-1 1,-1,1 -1,1,1 -1,1,-1 1,1,-1 1,1,1 -1,-1,1 -1,1,1 1,1,1 1,-1,1 -1,-1,-1 -1,1,-1 1,1,-1 1,-1,-1 -1,-1,1 -1,1,1 -1,1,-1 -1,-1,-1 1,-1,1 1,1,1 1,1,-1 1,-1,-1" />
</Window.Resources>
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camera" Position="-2,2,5" LookDirection="2,-2,-5" FieldOfView="90" />
</Viewport3D.Camera>
<!-- 3D 元素的容器 -->
<ContainerUIElement3D x:Name="container">
<ContainerUIElement3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0, 1, 0" Angle="0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</ContainerUIElement3D.Transform>
<!-- 完整的3D元素,包括路由事件 -->
<ModelUIElement3D MouseDown="Cube1_MouseDown">
<ModelUIElement3D.Transform>
<Transform3DGroup>
<TranslateTransform3D OffsetZ="1.5" />
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0, 1, 0" Angle="0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</ModelUIElement3D.Transform>
<ModelUIElement3D.Model>
<GeometryModel3D Geometry="{StaticResource CubeMesh}">
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="cube1Material" Brush="Blue" />
</GeometryModel3D.Material>
</GeometryModel3D>
</ModelUIElement3D.Model>
</ModelUIElement3D>
</ContainerUIElement3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight Color="White" Direction="-1,-1,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Window>
以下是C#代码,它定义了ModelUIElement3D的事件处理程序。
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;
namespace Shapes
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Cube1_MouseDown(object sender, MouseButtonEventArgs e)
{
ModelUIElement3D currentObject = sender as ModelUIElement3D;
if (currentObject.Transform is Transform3DGroup)
{
RotateTransform3D rotateTrans = null;
Transform3DGroup transGroup = currentObject.Transform as Transform3DGroup;
rotateTrans = TryFindChild<RotateTransform3D>(transGroup);
if (rotateTrans != null)
{
// 旋转对象360度
DoubleAnimation doubleAnimation = new DoubleAnimation(0, 360, new Duration(TimeSpan.FromSeconds(0.5)));
rotateTrans.Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, doubleAnimation);
}
}
}
public static T TryFindChild<T>(Transform3DGroup parent) where T : DependencyObject
{
foreach (DependencyObject child in parent.Children)
{
if (child is T)
{
return child as T;
}
}
return null;
}
}
}