Я собрал некоторый код, в котором я манипулирую двумя объектами Helix Toolkit Torus с помощью ползунковых элементов управления WPF. Этот код является прототипом для некоторой другой более сложной проблемы.
Когда я применяю только Трансформацию или Трансформацию вращения, объекты Тора перемещаются или вращаются. Тем не менее, когда я применил только последний из перечисленных в оде работ (Вращение в этом примере). Если я закомментирую Rotation Transform, переводы сработают.
Я попробовал подход TransformGroup, тогда ничего не работает, кроме объектов зависимостей, определенных в наборе инструментов Helix (например, TorusDiameter).
Как вы можете видеть из кода, только одно преобразование предназначено для одновременной работы одного ползунка.
У меня два вопроса:
(1) Почему несколько приложений (строк) Transform не работают? Как я могу заставить это работать?
(2) Я поместил ящик сообщений в обработчик событий MyTorusChanged. Кажется, уволили только в начале. Я новичок в WPF. Как Transform работает без прохождения обработчика событий?
Модель представления:
// April 08, 2019, Dr. I. Konuk
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using HelixToolkit.Wpf;
namespace AnimatedTorusDemo
{
class MyTorusViewModel : ModelVisual3D
{
// origin of torus object
public Point3D TorusOrigin { get; set; }
public double translationX { get; set; }
public double translationY { get; set; }
public double translationZ { get; set; }
// translation transformation parameter properties
public static readonly DependencyProperty TranslationXProperty =
DependencyProperty.Register("TranslationX", typeof(double), typeof(MyTorusViewModel),
new UIPropertyMetadata(0.0));
public static readonly DependencyProperty TranslationYProperty =
DependencyProperty.Register("TranslationY", typeof(double), typeof(MyTorusViewModel),
new UIPropertyMetadata(0.0));
public static readonly DependencyProperty TranslationZProperty =
DependencyProperty.Register("TranslationZ", typeof(double), typeof(MyTorusViewModel),
new UIPropertyMetadata(0.0));
public double TranslationX
{
get { return (double)GetValue(TranslationXProperty); }
set { SetValue(TranslationXProperty, value); translationX = value; }
}
public double TranslationY
{
get { return (double)GetValue(TranslationYProperty); }
set { SetValue(TranslationYProperty, value); translationY = value; }
}
public double TranslationZ
{
get { return (double)GetValue(TranslationZProperty); }
set { SetValue(TranslationZProperty, value); translationZ = value; }
}
// MyTorusProperty
// notice the callback function definition via Metadata
public static DependencyProperty MyTorusProperty =
DependencyProperty.Register("MyTorus", typeof(TorusVisual3D), typeof(MyTorusViewModel),
new UIPropertyMetadata(null, MyTorusChanged));
public TorusVisual3D MyTorus
{
get => (TorusVisual3D)GetValue(MyTorusProperty);
set { SetValue(MyTorusProperty, value); }
}
// rotation angle property
// Gets or sets the rotation angle (angle of torus).
public static readonly DependencyProperty RotationAngleProperty =
DependencyProperty.Register("RotationAngle", typeof(double), typeof(MyTorusViewModel),
new UIPropertyMetadata(45.0));
public double RotationAngle
{
get { return (double)GetValue(RotationAngleProperty); }
set { SetValue(RotationAngleProperty, value); }
}
public static AxisAngleRotation3D axisAngleRotation = new AxisAngleRotation3D(new Vector3D(1, 0, 0), 0);
public static readonly DependencyProperty TorusAxisAngleProperty =
DependencyProperty.Register("TorusAxisAngle", typeof(AxisAngleRotation3D), typeof(MyTorusViewModel),
new UIPropertyMetadata(axisAngleRotation));
public AxisAngleRotation3D TorusAxisAngle
{
get { return (AxisAngleRotation3D)GetValue(TorusAxisAngleProperty); }
set { SetValue(TorusAxisAngleProperty, value); }
}
// callback function used updating visuals (torus obejects)
protected static void MyTorusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
((MyTorusViewModel)obj).UpdateVisuals();
}
// member function to update visuals
private void UpdateVisuals()
{
MessageBox.Show("UpdateVisuals");
Children.Clear();
// each instance must have a torus object assigned for each MyTorusViewModel before
if (MyTorus == null) return;
MyTorus.ThetaDiv = 36;
MyTorus.PhiDiv = 24;
// translation
var torusTranslate = new TranslateTransform3D(new Vector3D(translationX, translationY, translationZ));
MyTorus.Transform = torusTranslate;
// rotation
var torusRotate = new RotateTransform3D();
TorusAxisAngle = new AxisAngleRotation3D();
TorusAxisAngle.Axis= new Vector3D(0, 1, 0);
TorusAxisAngle.Angle = RotationAngle;
torusRotate.Rotation = TorusAxisAngle;
MyTorus.Transform = torusRotate;
// transform group
var torusTransformGroup = new Transform3DGroup();
torusTransformGroup.Children.Add(torusTranslate);
// MyTorus.Transform = torusTransformGroup;
Children.Add(MyTorus);
}
}
}
XAML:
<Window x:Class="AnimatedTorusDemo.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:h="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf"
xmlns:local="clr-namespace:AnimatedTorusDemo"
mc:Ignorable="d"
Title="MainWindow" Height="750" Width="800">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition Height="0.75*" />
<RowDefinition Height="0.75*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<h:HelixViewport3D x:Name="TorusView" ZoomExtentsWhenLoaded="True" ShowCoordinateSystem="True" PanGesture="LeftClick" >
<h:DefaultLights/>
</h:HelixViewport3D>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom" Opacity="0.9" >
<Slider x:Name="translationX1Slider" Value="0" Minimum="-5.0" Maximum="5.0" Width="150" Margin="10"
/>
<Slider x:Name="translationY1Slider" Value="0" Minimum="-5.0" Maximum="5.0" Width="150" Margin="10"
/>
<Slider x:Name="translationZ1Slider" Value="1" Minimum="-3" Maximum="3" Width="150" Margin="10"
/>
<Slider x:Name="rotation1Slider" Value="45" Minimum="0" Maximum="360" Width="150" Margin="10"
/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom" Opacity="0.9" >
<Slider x:Name="translationX2Slider" Value="0" Minimum="-5.0" Maximum="5.0" Width="150" Margin="10"
/>
<Slider x:Name="translationY2Slider" Value="0" Minimum="-5" Maximum="5" Width="150" Margin="10"
/>
<Slider x:Name="translationZ2Slider" Value="-1" Minimum="-3" Maximum="3" Width="150" Margin="10"
/>
<Slider x:Name="rotation2Slider" Value="45" Minimum="0" Maximum="360" Width="150" Margin="10"
/>
</StackPanel>
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom" Opacity="0.9" >
<Slider x:Name="torusDiameterSlider" Minimum="1" Maximum="10" Width="150" Margin="10"
/>
<Slider x:Name="tubeDiameterSlider" Value="1" Minimum="0.5" Maximum="5" Width="150" Margin="10"
/>
<Slider x:Name="thetaDivSlider" Value="36" Minimum="3" Maximum="256" Width="150" Margin="10"
/>
<Slider x:Name="phiDivSlider" Value="24" Minimum="3" Maximum="256" Width="150" Margin="10"/>
</StackPanel>
</Grid>
</Window>
главное окно:
// April 08, 2019, Dr. I. Konuk
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Media.Media3D;
using HelixToolkit.Wpf;
namespace AnimatedTorusDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly ModelVisual3D model;
private MyTorusViewModel visual1;
private MyTorusViewModel visual2;
public MainWindow()
{
InitializeComponent();
model = new ModelVisual3D();
visual1 = new MyTorusViewModel();
var mytorus1 = new TorusVisual3D();
mytorus1.Fill = Brushes.Red;
visual1.MyTorus = mytorus1;
visual2 = new MyTorusViewModel();
var mytorus2 = new TorusVisual3D();
mytorus2.Fill = Brushes.Blue;
visual2.MyTorus = mytorus2;
mytorus2.TorusDiameter = 5;
// bindings with sliders in code
// Helix Toolkit dependencyproperties:
// a) Geometry:
BindingOperations.SetBinding(mytorus1, HelixToolkit.Wpf.TorusVisual3D.TorusDiameterProperty,
new Binding("Value") { Source = torusDiameterSlider });
BindingOperations.SetBinding(mytorus1, HelixToolkit.Wpf.TorusVisual3D.TubeDiameterProperty,
new Binding("Value") { Source = tubeDiameterSlider });
// b) Translation:
// Dependency properties defined in MyTorusView Model
BindingOperations.SetBinding(mytorus1.Transform, TranslateTransform3D.OffsetXProperty,
new Binding("Value") { Source = translationX1Slider });
BindingOperations.SetBinding(mytorus1.Transform, TranslateTransform3D.OffsetYProperty,
new Binding("Value") { Source = translationY1Slider });
BindingOperations.SetBinding(mytorus1.Transform, TranslateTransform3D.OffsetZProperty,
new Binding("Value") { Source = translationZ1Slider });
BindingOperations.SetBinding(mytorus2.Transform, TranslateTransform3D.OffsetXProperty,
new Binding("Value") { Source = translationX2Slider });
BindingOperations.SetBinding(mytorus2.Transform, TranslateTransform3D.OffsetYProperty,
new Binding("Value") { Source = translationY2Slider });
BindingOperations.SetBinding(mytorus2.Transform, TranslateTransform3D.OffsetZProperty,
new Binding("Value") { Source = translationZ2Slider });
// b) Rotation
BindingOperations.SetBinding(visual1.TorusAxisAngle, AxisAngleRotation3D.AngleProperty,
new Binding("Value") { Source = rotation1Slider });
BindingOperations.SetBinding(visual2.TorusAxisAngle, AxisAngleRotation3D.AngleProperty,
new Binding("Value") { Source = rotation2Slider });
model.Children.Add(visual1);
model.Children.Add(visual2);
TorusView.Children.Add(model);
this.DataContext = this;
}
}
}