上一节展示了鼠标拖动改变图片位置和大小,下面介绍下鼠标拖动和控件之间的双向绑定展示,效果如下:
实现步骤:
1、MyImage自定义控件与博文WPF中GDI+图形图像的绘制:(七)绘制图像——鼠标拖动改变位置和大小中一致
2、主窗体xaml
<Window x:Class="DrawDemo.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:local="clr-namespace:DrawDemo"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize"
Title="控件绑定" Height="768" Width="1280">
<Grid Background="#f0f0f0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition ></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="380"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Canvas x:Name="mainCanvas" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Background="White" Width="960" Height="720" Margin="10,5,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top" ClipToBounds="True"
MouseLeftButtonDown="mainCanvas_MouseLeftButtonDown" MouseLeftButtonUp="mainCanvas_MouseLeftButtonUp" MouseMove="mainCanvas_MouseMove">
</Canvas>
<GroupBox Grid.Row="0" Grid.Column="1" Margin="10" Header="控件绑定">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="选择图片" VerticalAlignment="Center" HorizontalAlignment="Right"></Label>
<Button x:Name="btnChooseImg" Grid.Row="0" Grid.Column="1" Content="选择" VerticalAlignment="Center" HorizontalAlignment="Left" Height="26" Width="80" Margin="10,0,0,0" Click="btnChooseImg_Click"></Button>
<Label Grid.Row="1" Grid.Column="0" Content="X坐标" VerticalAlignment="Center" HorizontalAlignment="Right"></Label>
<wfi:WindowsFormsHost Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Height="26" Width="80" Margin="10,0,0,0">
<winForms:NumericUpDown x:Name="locationX" Minimum="0" Maximum="9999" ValueChanged="LocationX_ValueChanged"></winForms:NumericUpDown>
</wfi:WindowsFormsHost>
<Label Grid.Row="2" Grid.Column="0" Content="Y坐标" VerticalAlignment="Center" HorizontalAlignment="Right"></Label>
<wfi:WindowsFormsHost Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Height="26" Width="80" Margin="10,0,0,0">
<winForms:NumericUpDown x:Name="locationY" Minimum="0" Maximum="9999" ValueChanged="LocationY_ValueChanged"></winForms:NumericUpDown>
</wfi:WindowsFormsHost>
<Label Grid.Row="3" Grid.Column="0" Content="宽" VerticalAlignment="Center" HorizontalAlignment="Right"></Label>
<wfi:WindowsFormsHost Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Height="26" Width="80" Margin="10,0,0,0">
<winForms:NumericUpDown x:Name="imgWidth" Minimum="0" Maximum="9999" ValueChanged="ImgWidth_ValueChanged"></winForms:NumericUpDown>
</wfi:WindowsFormsHost>
<Label Grid.Row="4" Grid.Column="0" Content="高" VerticalAlignment="Center" HorizontalAlignment="Right"></Label>
<wfi:WindowsFormsHost Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Height="26" Width="80" Margin="10,0,0,0">
<winForms:NumericUpDown x:Name="imgHeight" Minimum="0" Maximum="9999" ValueChanged="ImgHeight_ValueChanged"></winForms:NumericUpDown>
</wfi:WindowsFormsHost>
</Grid>
</GroupBox>
</Grid>
</Window>
3、鼠标按下抬起、拖动改变图片位置和大小的逻辑同上节一致,不同的是加入了和NumericUpDown之间的双向绑定展示,逻辑交互如下:
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private Point pBefore = new Point();//鼠标点击前坐标
private Point eBefore = new Point();//图片移动前坐标
private double wBefore;//图片改变大小前宽
private double hBefore;//图片改变大小前高
private int minImgValue = 10;//图片最小宽高
private bool IsCanMove = false;//是否可以移动
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// 选择图片
/// </summary>
private void btnChooseImg_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "选择图片";
openFileDialog.Filter = "图片(*.jpg,*.png,*.bmp)|*.jpg;*.png;*.bmp"; ;
openFileDialog.FileName = string.Empty;
openFileDialog.Multiselect = false;
openFileDialog.InitialDirectory = @"C:\Image";
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
BitmapImage bi = ImageHelper.LoadBitmapImageByPath(openFileDialog.FileName);
if (bi != null)
{
MyImage imgPic = new MyImage();
imgPic.Source = bi;
imgPic.Width = bi.PixelWidth;
imgPic.Height = bi.PixelHeight;
this.mainCanvas.Children.Add(imgPic);
Canvas.SetLeft(imgPic, (this.mainCanvas.ActualWidth - bi.PixelWidth) / 2);
Canvas.SetTop(imgPic, (this.mainCanvas.ActualHeight - bi.PixelHeight) / 2);
}
}
}
/// <summary>
/// 鼠标按下
/// </summary>
private void mainCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
//获取点击前鼠标坐标
this.pBefore = e.GetPosition(this.mainCanvas);
//获取点击图片的坐标和位置
this.eBefore = new Point(Canvas.GetLeft(img), Canvas.GetTop(img));
this.wBefore = img.Width;
this.hBefore = img.Height;
//设置为可移动
IsCanMove = true;
//鼠标捕获此图片
img.CaptureMouse();
img.IsSelect = true;
img.InvalidateVisual();
//展示XY坐标
ShowXY(img);
//展示宽高
ShowWH(img);
SetOtherUnSelect(img);
//改变鼠标样式
this.Cursor = System.Windows.Input.Cursors.SizeAll;
}
else
{
SetOtherUnSelect();
}
}
/// <summary>
/// 鼠标抬起
/// </summary>
private void mainCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
//设置为不可移动
IsCanMove = false;
//鼠标释放此图片
img.ReleaseMouseCapture();
img.InvalidateVisual();
this.Cursor = System.Windows.Input.Cursors.Arrow;
}
}
/// <summary>
/// 鼠标移动
/// </summary>
private void mainCanvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (!IsCanMove)
return;
if (e.OriginalSource != null && e.LeftButton == MouseButtonState.Pressed)
{
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
if (IsCanMove && img != null)
{
MoveChange(e, img.changeType);
}
}
else
{
base.OnMouseMove(e);
}
}
else
this.Cursor = System.Windows.Input.Cursors.Arrow;
}
/// <summary>
/// 移动改变坐标或大小
/// </summary>
private void MoveChange(System.Windows.Input.MouseEventArgs e, ChangeType changeType)
{
try
{
switch (changeType)
{
case ChangeType.ChangeLeftTop:
setLTvp(e);
break;
case ChangeType.ChangeRightTop:
setRTvp(e);
break;
case ChangeType.ChangeRightBottom:
setRBvp(e);
break;
case ChangeType.ChangeLeftBottom:
setLBvp(e);
break;
case ChangeType.Move:
MyImage img = (MyImage)e.OriginalSource;
if (img != null)
MoveImage(e);
break;
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// 移动对象
/// </summary>
public void MoveImage(System.Windows.Input.MouseEventArgs e)
{
MyImage img = (MyImage)e.OriginalSource;
//获取鼠标移动中的坐标
Point p = e.GetPosition(this.mainCanvas);
//计算拖拽距离
double dragx = p.X - pBefore.X;
double dragy = p.Y - pBefore.Y;
//当拖拽距离大于一定范围时改变控件位置
if(Math.Abs(dragx) > 5 || Math.Abs(dragy) > 5)
{
Canvas.SetLeft(img, eBefore.X + dragx);
Canvas.SetTop(img, eBefore.Y + dragy);
img.InvalidateVisual();
ShowXY(img);
}
}
/// <summary>
/// 左上角拖动
/// </summary>
public void setLTvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
if ((wBefore - changeX) > minImgValue)
{
Canvas.SetLeft(img, eBefore.X + changeX);
img.Width = wBefore - changeX;
}
else
{
img.Width = minImgValue;
}
if ((hBefore - changeY) > minImgValue)
{
Canvas.SetTop(img, eBefore.Y + changeY);
img.Height = hBefore - changeY;
}
else
{
img.Height = minImgValue;
}
img.InvalidateVisual();
ShowXY(img);
ShowWH(img);
}
}
/// <summary>
/// 右上角拖动
/// </summary>
public void setRTvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
img.Width = (wBefore + changeX) > minImgValue ? wBefore + changeX : minImgValue;
if ((hBefore - changeY) > minImgValue)
{
Canvas.SetTop(img, eBefore.Y + changeY);
img.Height = hBefore - changeY;
}
else
{
img.Height = minImgValue;
}
img.InvalidateVisual();
ShowXY(img);
ShowWH(img);
}
}
/// <summary>
/// 左下角拖动
/// </summary>
public void setLBvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
if ((wBefore - changeX) > minImgValue)
{
Canvas.SetLeft(img, eBefore.X + changeX);
img.Width = wBefore - changeX;
}
else
{
img.Width = minImgValue;
}
img.Height = (hBefore + changeY) > minImgValue ? hBefore + changeY : minImgValue;
img.InvalidateVisual();
ShowXY(img);
ShowWH(img);
}
}
/// <summary>
/// 右下角拖动
/// </summary>
public void setRBvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
img.Width = (wBefore + changeX) > minImgValue ? wBefore + changeX : minImgValue;
img.Height = (hBefore + changeY) > minImgValue ? hBefore + changeY : minImgValue;
img.InvalidateVisual();
ShowWH(img);
}
}
/// <summary>
/// 设置其他为未选择状态
/// </summary>
public void SetOtherUnSelect(object myImage = null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this.mainCanvas); i++)
{
if (VisualTreeHelper.GetChild(this.mainCanvas, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this.mainCanvas, i);
if (myImage == null)
{
child.IsSelect = false;
child.InvalidateVisual();
}
else if (myImage != child)
{
if (child.IsSelect)
{
child.IsSelect = false;
child.InvalidateVisual();
}
}
}
}
}
/// <summary>
/// 展示XY坐标
/// </summary>
private void ShowXY(MyImage img)
{
this.locationX.Value = Convert.ToDecimal(Canvas.GetLeft(img));
this.locationY.Value = Convert.ToDecimal(Canvas.GetTop(img));
}
/// <summary>
/// 展示img宽高
/// </summary>
private void ShowWH(MyImage img)
{
this.imgWidth.Value = Convert.ToDecimal(img.Width);
this.imgHeight.Value = Convert.ToDecimal(img.Height);
}
/// <summary>
/// X坐标改变事件
/// </summary>
private void LocationX_ValueChanged(object sender, EventArgs e)
{
if (IsCanMove)
return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this.mainCanvas); i++)
{
if (VisualTreeHelper.GetChild(this.mainCanvas, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this.mainCanvas, i);
if (child.IsSelect)
{
Canvas.SetLeft(child, Convert.ToDouble(this.locationX.Value));
child.InvalidateVisual();
}
}
}
}
/// <summary>
/// Y坐标改变事件
/// </summary>
private void LocationY_ValueChanged(object sender, EventArgs e)
{
if (IsCanMove)
return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this.mainCanvas); i++)
{
if (VisualTreeHelper.GetChild(this.mainCanvas, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this.mainCanvas, i);
if (child.IsSelect)
{
Canvas.SetTop(child, Convert.ToDouble(this.locationY.Value));
child.InvalidateVisual();
}
}
}
}
/// <summary>
/// 宽改变事件
/// </summary>
private void ImgWidth_ValueChanged(object sender, EventArgs e)
{
if (IsCanMove)
return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this.mainCanvas); i++)
{
if (VisualTreeHelper.GetChild(this.mainCanvas, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this.mainCanvas, i);
if (child.IsSelect)
{
child.Width = Convert.ToDouble(this.imgWidth.Value);
child.InvalidateVisual();
}
}
}
}
/// <summary>
/// 高改变事件
/// </summary>
private void ImgHeight_ValueChanged(object sender, EventArgs e)
{
if (IsCanMove)
return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this.mainCanvas); i++)
{
if (VisualTreeHelper.GetChild(this.mainCanvas, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this.mainCanvas, i);
if (child.IsSelect)
{
child.Height = Convert.ToDouble(this.imgHeight.Value);
child.InvalidateVisual();
}
}
}
}
}
相关博文:
WPF中GDI+图形图像的绘制:(一)绘制文本——动态设置字体、大小、颜色
WPF中GDI+图形图像的绘制:(二)绘制文本——字体描边、渐变、图片叠加
WPF中GDI+图形图像的绘制:(三)绘制图像——实现黑白、浮雕、锐化效果
WPF中GDI+图形图像的绘制:(四)绘制图像——水平垂直镜像与中心旋转
WPF中GDI+图形图像的绘制:(五)绘制图像——蒙板效果
WPF中GDI+图形图像的绘制:(六)绘制图像——鼠标选中后绘制边框
WPF中GDI+图形图像的绘制:(七)绘制图像——鼠标拖动改变位置和大小
WPF中GDI+图形图像的绘制:(八)位置坐标和宽高与控件绑定展示