在我的 WPF MVVM 应用程序中,我有一个 ListBox
与 Canvas
作为其 ItemsPanel
. ListBox 的项目由用户在单击按钮时动态创建 - ListBox.ItemsSource
是存储在我的 MainViewModel
中的自定义类型的项目列表这是 DataContext
我的MainWindow
.我希望用户能够使用一组 Thumb
来旋转项目控件附加到每个 ListBoxItem
.到目前为止,我在尝试找到可行的解决方案时收效甚微,我变得非常绝望。
这是我的 ListBoxItem
中最重要的部分的风格:
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
<Setter Property="Width" Value="{Binding Width}"/>
<Setter Property="Height" Value="{Binding Height}"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource EmptyFocusVisualStyle}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem" >
<Grid>
<Control Name="RotateDecorator"
Width="{Binding Width}" Height="{Binding Height}"
Template="{StaticResource RotateDecoratorTemplate}"
Visibility="Visible"/>
<ContentPresenter x:Name="Content" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
在这里你可以看到它的样子:http://screenshooter.net/100101493/dhokpue
RotateDecorator
本质上只是一组稍微定制的 Thumb
我想旋转 ListBoxItem
的控件(在图片中显示为所选项目周围的小三角形) .但是我完全没有关于如何做到这一点的想法。我唯一知道的是我需要写合适的 DragDelta
和 DragStarted
作为事件处理程序的方法。有什么想法可以缓解我的愤怒吗?
编辑:这里是 DragStarted
和 DragDelta
RotationThumb
的方法.它们会影响移动 Thumb 的行为方式吗?
开始拖动:
private void RotateThumb_DragStarted(object sender, DragStartedEventArgs e)
{
var thumb = sender as RotateThumb;
var parent = VisualTreeHelper.GetParent(thumb);
for (int i = 0; i < 3; i++ )
{
parent = VisualTreeHelper.GetParent(parent);
}
this.designerItem = parent as ListBoxItem;
if (this.designerItem != null)
{
this.designerCanvas = VisualTreeHelper.GetParent(this.designerItem) as Canvas;
if (this.designerCanvas != null)
{
this.centerPoint = this.designerItem.TranslatePoint(
new Point(this.designerItem.Width * this.designerItem.RenderTransformOrigin.X,
this.designerItem.Height * this.designerItem.RenderTransformOrigin.Y),
this.designerCanvas);
Point startPoint = Mouse.GetPosition(this.designerCanvas);
this.startVector = Point.Subtract(startPoint, this.centerPoint);
this.rotateTransform = this.designerItem.RenderTransform as RotateTransform;
if (this.rotateTransform == null)
{
this.designerItem.RenderTransform = new RotateTransform(0);
this.initialAngle = 0;
}
else
{
this.initialAngle = this.rotateTransform.Angle;
}
}
}
}
拖动增量:
private void RotateThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (this.designerItem != null && this.designerCanvas != null)
{
Point currentPoint = Mouse.GetPosition(this.designerCanvas);
Vector deltaVector = Point.Subtract(currentPoint, this.centerPoint);
double angle = Vector.AngleBetween(this.startVector, deltaVector);
RotateTransform rotateTransform = this.designerItem.RenderTransform as RotateTransform;
rotateTransform.Angle = this.initialAngle + Math.Round(angle, 0);
this.designerItem.InvalidateMeasure();
}
}
EDIT2:问题已解决
最佳答案
有几种方法,但这里有一些伪代码可以帮助您入门:
// for every drag event
Point a = listboxitem center position (or wherever you want the rotation origin)
Point b = position before drag
Point c = position after drag
// calculate and normalize vectors a-b and a-c
Vector v1 = ( b - a ).Normalized();
Vector v2 = ( c - a ).Normalized();
// calculate angles for v1 and v2 (in radians)
double a1 = Math.Atan2( v1.y, v1.x );
double a2 = Math.Atan2( v2.y, v2.x );
// the amount of rotation is then the difference between a1 and a2
// NOTE: there's a catch here, Atan2 returns angles = -π ≤ θ ≤ π, so
// the values might wrap around, which you'll need to take care of too
double angleInRadians = a2 - a1;
double angleInDegrees = ( angleInRadians / Math.PI ) * 180.0;
然后将这个角度添加到您放置在 ListBoxItem
上的 RotateTransform
的角度。
关于c# - 如何在 Canvas 上旋转动态创建的 ListBoxItem?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24970720/