Выберите сгенерированный во время выполнения куб в HelixViewport3D
Я использую Helix3DToolkit и пытаюсь сделать выборку для куба, который генерируется во время выполнения. Куб имеет тип SelectableCube, который является производным от UIElement3D. Если я просто добавляю куб во время инициализации MainWindow, все работает нормально, и я могу выбрать и отменить выбор куба по своему усмотрению.
Посмотреть изображение приложения с выбранным кубом
Если куб добавлен в соответствии с настройками ползунков, он не может быть выбран и не реагирует на MouseOver и MouseLeave. Зачем?
Кубы, созданные в соответствии со значениями слайдера
Я знаю, что мог бы реализовать механизм тестирования попаданий, чтобы проверить, какой куб был выбран, но я не понимаю, почему в этом случае не вызываются обработчики событий в классе SelectableCube? Какая разница в рабочем случае?
Мой код до сих пор:
public class SelectableCube : UIElement3D
{
public Point3D Center
{
get { return (Point3D)GetValue(CenterProperty); }
set { SetValue(CenterProperty, value);
}
}
// Using a DependencyProperty as the backing store for Center. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CenterProperty =
DependencyProperty.Register("Center", typeof(Point3D), typeof(SelectableCube),new PropertyMetadata(CenterChangeCallback));
private static void CenterChangeCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((SelectableCube)d).SetCurrentValue(CenterProperty, (Point3D)e.NewValue);
MeshBuilder builder = new MeshBuilder();
builder.AddBox(((SelectableCube)d).Center, 1, 1, 1);
GeometryModel3D model = new GeometryModel3D(builder.ToMesh(), MaterialHelper.CreateMaterial(new SolidColorBrush(Color.FromRgb(255, 0, 0))));
((SelectableCube)d).Visual3DModel = model;
}
public SelectableCube()
{
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
GeometryModel3D g = Visual3DModel as GeometryModel3D;
if (!g.Material.Equals(Materials.Gold))
{
g.Material = Materials.Gray;
}
e.Handled = true;
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
GeometryModel3D g = Visual3DModel as GeometryModel3D;
if (!g.Material.Equals(Materials.Gold))
{
g.Material = Materials.LightGray;
}
e.Handled = true;
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
GeometryModel3D g = Visual3DModel as GeometryModel3D;
if (g.Material.Equals(Materials.Gold))
{
g.Material = Materials.Gray;
}
else
{
g.Material = Materials.Gold;
}
e.Handled = true;
}
}
//
public partial class MainWindow : Window
{
public Visual3DCollection Cubes { get; set; }
public MainWindow()
{
InitializeComponent();
this.MainViewport.MouseDown += MainViewport_MouseDown;
ContainerUIElement3D col = this.MainViewport.Children.FirstOrDefault(x => x.GetType().Equals(typeof(ContainerUIElement3D))) as ContainerUIElement3D;
ModelVisual3D cubeContainer = col.Children[0] as ModelVisual3D;
Cubes = cubeContainer.Children;
Cubes.Add(new SelectableCube() { Center = new Point3D(1,1,1)});
}
private void MainViewport_MouseDown(object sender, MouseButtonEventArgs e)
{
Point pointerLocation = e.GetPosition(this.MainViewport);
HitTestResult res = VisualTreeHelper.HitTest(this.MainViewport, pointerLocation);
}
private void ColSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Redraw();
}
private void RowSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Redraw();
}
private void Redraw()
{
Cubes.Clear();
for (int row = 1; row <= this.RowSlider.Value; row++)
{
for (int col = 1; col <= this.ColSlider.Value; col++)
{
SelectableCube c = new SelectableCube() { Center = new Point3D(row + (row - 1) * this.DistanceSlider.Value, col + (col - 1) + this.DistanceSlider.Value, 5) };
Cubes.Add(c);
}
}
}
}
Код XAML:
<Window x:Class="HelixTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:HelixToolkit="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf"
xmlns:local="clr-namespace:HelixTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<HelixToolkit:HelixViewport3D Grid.Column="0" ZoomExtentsWhenLoaded="True" Name="MainViewport">
<HelixToolkit:SunLight/>
<ContainerUIElement3D>
<ModelVisual3D/>
</ContainerUIElement3D>
<HelixToolkit:GridLinesVisual3D Width="8" Length="8" MinorDistance="1" MajorDistance="1" Thickness="0.01"/>
</HelixToolkit:HelixViewport3D>
<StackPanel Grid.Column="1" Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Label Content="# Columns:"/>
<Slider Name="ColSlider" Width="120" Maximum="100"
TickFrequency="1" IsSnapToTickEnabled="True"
ValueChanged="ColSlider_ValueChanged"></Slider>
<Label Content="{Binding ElementName=ColSlider, Path=Value}"></Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="# Rows:"/>
<Slider Name="RowSlider" Width="120" Maximum="100"
TickFrequency="1" IsSnapToTickEnabled="True"
ValueChanged="RowSlider_ValueChanged"></Slider>
<Label Content="{Binding ElementName=RowSlider, Path=Value}"></Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="# Distance:"/>
<Slider Name="DistanceSlider" Width="120" Maximum="2"
TickFrequency="0.1" IsSnapToTickEnabled="True"
ValueChanged="DistanceSlider_ValueChanged"></Slider>
<Label Content="{Binding ElementName=DistanceSlider, Path=Value}"></Label>
</StackPanel>
</StackPanel>
</Grid>