调整大小或移动裁剪矩形后裁剪图像

时间:2015-03-11 12:08:14

标签: c# wpf xaml mvvm

我为我的程序实现了一个裁剪用户控件,我想添加可移动和可调整大小的功能。我目前正在关注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值,但我不确定如何实现它。任何建议将不胜感激

1 个答案:

答案 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));