我为我的程序实现了一个裁剪用户控件,我想添加可移动和可调整大小的功能。我目前正在关注Sukrahms Diagram Designer http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part-1。但是因为我的矩形不是在用户拖动并制作矩形之后才创建的,所以我得到了意想不到的结果。现在我只是想创建一个包含在ContentControl中的矩形,但是当我拖动鼠标来创建一个矩形时,它会在窗口的最左边缘而不是在我点击鼠标左键的位置。以下是我的代码。
XAML:
<UserControl x:Class="Klein_Tools_Profile_Pic_Generator.CropControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="clr-namespace:Klein_Tools_Profile_Pic_Generator"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type s:MoveThumb}">
<Rectangle Fill="Transparent"/>
</ControlTemplate>
<!-- ResizeDecorator Template -->
<ControlTemplate x:Key="ResizeDecoratorTemplate" TargetType="{x:Type Control}">
<Grid>
<s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 -4 0 0"
VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<s:ResizeThumb Width="3" Cursor="SizeWE" Margin="-4 0 0 0"
VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
<s:ResizeThumb Width="3" Cursor="SizeWE" Margin="0 0 -4 0"
VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
<s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 0 0 -4"
VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
<s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0"
VerticalAlignment="Top" HorizontalAlignment="Left"/>
<s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0"
VerticalAlignment="Top" HorizontalAlignment="Right"/>
<s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6"
VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6"
VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
</Grid>
</ControlTemplate>
<!-- Designer Item Template-->
<ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
<Control Template="{StaticResource ResizeDecoratorTemplate}"/>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<Canvas x:Name="BackPanel"
MouseLeftButtonDown="LoadedImage_MouseLeftButtonDown"
MouseMove="LoadedImage_MouseMove"
MouseLeftButtonUp="LoadedImage_MouseLeftButtonUp"
Background="Transparent">
<ContentControl x:Name="contControl" Visibility="Collapsed"
Template="{StaticResource DesignerItemTemplate}">
<Rectangle x:Name="selectionRectangle" Fill="#220000FF"
IsHitTestVisible="False"/>
</ContentControl>
</Canvas>
</UserControl>
用户控制CodeBehind:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Shapes;
namespace Klein_Tools_Profile_Pic_Generator
{
/// <summary>
/// Interaction logic for CropControl.xaml
/// </summary>
public partial class CropControl : UserControl
{
private bool isDragging = false;
private Point anchorPoint = new Point();
public CropControl()
{
InitializeComponent();
}
//Register the Dependency Property
public static readonly DependencyProperty SelectionProperty =
DependencyProperty.Register("Selection", typeof(Rect), typeof(CropControl), new PropertyMetadata(default(Rect)));
public Rect Selection
{
get { return (Rect)GetValue(SelectionProperty); }
set { SetValue(SelectionProperty, value); }
}
// this is used, to react on changes from ViewModel. If you assign a
// new Rect in your ViewModel you will have to redraw your Rect here
private static void OnSelectionChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
{
Rect newRect = (Rect)e.NewValue;
Rectangle selectionRectangle = d as Rectangle;
if (selectionRectangle != null)
return;
selectionRectangle.SetValue(Canvas.LeftProperty, newRect.X);
selectionRectangle.SetValue(Canvas.TopProperty, newRect.Y);
selectionRectangle.Width = newRect.Width;
selectionRectangle.Height = newRect.Height;
}
private void LoadedImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (isDragging == false)
{
anchorPoint.X = e.GetPosition(BackPanel).X;
anchorPoint.Y = e.GetPosition(BackPanel).Y;
Canvas.SetZIndex(selectionRectangle, 999);
isDragging = true;
BackPanel.Cursor = Cursors.Cross;
}
}
private void LoadedImage_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
double x = e.GetPosition(BackPanel).X;
double y = e.GetPosition(BackPanel).Y;
contControl.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X));
contControl.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y));
contControl.Width = Math.Abs(x - anchorPoint.X);
contControl.Height = Math.Abs(y - anchorPoint.Y);
if (contControl.Visibility != Visibility.Visible)
contControl.Visibility = Visibility.Visible;
}
}
private void LoadedImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragging)
{
isDragging = false;
if (contControl.Width > 0)
{
//Crop.IsEnabled = true;
//Cut.IsEnabled = true;
BackPanel.Cursor = Cursors.Arrow;
}
contControl.GetValue(Canvas.LeftProperty);
// Set the Selection to the new rect, when the mouse button has been released
Selection = new Rect(
(double)contControl.GetValue(Canvas.LeftProperty),
(double)contControl.GetValue(Canvas.TopProperty),
contControl.Width,
contControl.Height);
}
}
}
}
我想我需要从Rectangle中检索Canvas.Top和Canvas.Bottom,将它绑定到我的ContentControl,但我不知道如何。我到处寻找,我无法想出任何东西。我应该如何检索这个附加属性,还是有更好的方法来实现可移动和可调整大小的裁剪矩形?
更新
我根据Toby的建议对我的代码做了一些调整,现在裁剪矩形移动并按预期调整大小。最初在用户拖动鼠标并创建矩形后,它会正常裁剪,但是当我移动或调整相同的矩形时,它不会裁剪。如果它被移动或调整大小,我需要一些方法来改变代码隐藏中矩形的维度和X / Y值,但我不确定如何实现它。任何建议将不胜感激
答案 0 :(得分:0)
我认为问题可能与嵌入在ContentControl中的Rectangle有关。请尝试以下方法:
<Canvas x:Name="BackPanel" MouseLeftButtonDown="LoadedImage_MouseLeftButtonDown" MouseMove="LoadedImage_MouseMove" MouseLeftButtonUp="LoadedImage_MouseLeftButtonUp" Background="Transparent">
<Canvas.Resources>
<ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
</ControlTemplate>
</Canvas.Resources>
<Rectangle x:Name="selectionRectangle" Stroke="LightBlue" Fill="#220000FF" Visibility="Collapsed" />
</Canvas>
当Rectangle不在画布上时,而是在画布上的ContentControl中:
selectionRectangle.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X));
selectionRectangle.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y));
这些附加属性似乎不能按预期工作。 如果您需要将Rectangle放在ContentControl中,您可以在ContentControl本身(它是Canvas上的子项)上设置附加属性
contentControl.SetValue(Canvas.LeftProperty, Math.Min(x, anchorPoint.X));
contentControl.SetValue(Canvas.TopProperty, Math.Min(y, anchorPoint.Y));