再次感谢楼上各位的回复,其实我想实现从ListBox中拖拽一个图片到Canvas上,然后在Canvas上对图片进行缩放、旋转等操作。
经过整理,基本实现了以上功能,但略有出入,且界面粗糙。现把代码贴出来与大家共享。
<Window.Resources >
<MatrixTransform x:Key="InitialMatrixTransform">
<MatrixTransform.Matrix>
<Matrix OffsetX="0" OffsetY="0"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="210"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView PreviewMouseLeftButtonDown="StackPanel_PreviewMouseLeftButtonDown"
Grid.Column="0" Foreground="Gold" AllowDrop="True" x:Name="lstParent"
PreviewMouseMove="StackPanel_PreviewMouseMove" Margin="5,0,0,0"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ListViewItem Height="150">
<Image Source="Resources\Images\a01.jpg"></Image>
</ListViewItem>
<ListViewItem Height="150">
<Image Source="Resources\Images\a02.jpg"></Image>
</ListViewItem>
<ListViewItem Height="150">
<Image Source="Resources\Images\a03.jpg"></Image>
</ListViewItem>
<ListViewItem Height="150">
<Image Source="Resources\Images\a04.jpg"></Image>
</ListViewItem>
</ListView>
<Canvas x:Name="canvas" Grid.Column="1" AllowDrop="True"
Drop="Canvas_Drop" DragEnter="Canvas_DragEnter"
Width="Auto" Height="Auto" Background="WhiteSmoke"
RenderTransform="{StaticResource InitialMatrixTransform}"
IsManipulationEnabled="True"
ManipulationStarting="canvas_ManipulationStarting"
ManipulationInertiaStarting="canvas_ManipulationInertiaStarting"
ManipulationDelta="canvas_ManipulationDelta">
</Canvas>
</Grid>
Point startPoint;
ListBoxItem contact;
public Window4()
{
InitializeComponent();
}
private void StackPanel_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Routed Event");
}
private void Canvas_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("MyFormat"))
{
contact = e.Data.GetData("MyFormat") as ListBoxItem;
Canvas CanvasView = sender as Canvas;
this.lstParent.Items.Remove(contact);
CanvasView.Children.Add(contact);
}
}
private void Canvas_DragEnter(object sender, DragEventArgs e)
{
if (!(e.Data.GetDataPresent("contact")) || (sender == e.Source))
{
e.Effects = DragDropEffects.None;
}
}
private void StackPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(null);
}
private void StackPanel_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point mousPos = e.GetPosition(null);
Vector diff = startPoint - mousPos;
if ((e.LeftButton == MouseButtonState.Pressed) && (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance) && (Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
ListView listView = sender as ListView;
ListViewItem listViewItem = FindAnchestor<ListViewItem>((DependencyObject)e.OriginalSource);
if (listViewItem == null) { return; }
contact = (ListViewItem)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
DataObject dataObject = new DataObject("MyFormat", contact);
DragDrop.DoDragDrop(listViewItem, dataObject, DragDropEffects.Move);
}
}
private static T FindAnchestor<T>(DependencyObject current) where T : DependencyObject
{
do
{
if (current is T)
{
return (T)current;
}
current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}
private void canvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
e.ManipulationContainer = this.canvas;
e.Handled = true;
}
private void canvas_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
{
// Decrease the velocity of the Rectangle's movement by
// 10 inches per second every second.
// (10 inches * 96 DIPS per inch / 1000ms^2)
e.TranslationBehavior = new InertiaTranslationBehavior()
{
InitialVelocity = e.InitialVelocities.LinearVelocity,
DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0)
};
// Decrease the velocity of the Rectangle's resizing by
// 0.1 inches per second every second.
// (0.1 inches * 96 DIPS per inch / (1000ms^2)
e.ExpansionBehavior = new InertiaExpansionBehavior()
{
InitialVelocity = e.InitialVelocities.ExpansionVelocity,
DesiredDeceleration = 0.1 * 96 / 1000.0 * 1000.0
};
// Decrease the velocity of the Rectangle's rotation rate by
// 2 rotations per second every second.
// (2 * 360 degrees / (1000ms^2)
e.RotationBehavior = new InertiaRotationBehavior()
{
InitialVelocity = e.InitialVelocities.AngularVelocity,
DesiredDeceleration = 720 / (1000.0 * 1000.0)
};
e.Handled = true;
}
private void canvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
//this just gets the source.
// I cast it to FE because I wanted to use ActualWidth for Center. You could try RenderSize as alternate
var element = e.Source as FrameworkElement;
if (element != null)
{
//e.DeltaManipulation has the changes
// Scale is a delta multiplier; 1.0 is last size, (so 1.1 == scale 10%, 0.8 = shrink 20%)
// Rotate = Rotation, in degrees
// Pan = Translation, == Translate offset, in Device Independent Pixels
var deltaManipulation = e.DeltaManipulation;
var matrix = ((MatrixTransform)element.RenderTransform).Matrix;
// find the old center; arguaby this could be cached
Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);
// transform it to take into account transforms from previous manipulations
center = matrix.Transform(center);
//this will be a Zoom.
matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y);
// Rotation
matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);
//Translation (pan)
matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
((MatrixTransform)element.RenderTransform).Matrix = matrix;
e.Handled = true;
}
}