[英]Drawing dynamic Circle on WPF Canvas with MVVM
我已經在WPF中編寫了一個代碼,以便在Canvas中的Mouse Events上畫一個圓並將其拖到畫布上,並在后面的代碼中調整大小。 它的工作正常。 但是我需要使用MVVM框架實現相同的結果。
這是我的代碼,
XAML
<Window x:Class="testapp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
<Grid>
<Canvas x:Name="canvas" Background="Transparent" MouseDown="canvas_PreviewMouseDown" MouseMove="canvas_PreviewMouseMove" MouseUp="canvas_PreviewMouseUp"></Canvas>
</Grid>
</Window>
背后的代碼
private enum HitType
{
None, Body, UL, UR, LR, LL, L, R, T, B
};
private bool DragInProgress = false;
private Point LastPoint;
HitType MouseHitType = HitType.None;
Ellipse elip = new Ellipse();
private Point anchorPoint;
private bool is_drawing = false;
public MainWindow()
{
InitializeComponent();
}
private HitType SetHitType(Ellipse ellips, Point point)
{
double left = Canvas.GetLeft(ellips);
double top = Canvas.GetTop(ellips);
double right = left + ellips.Width;
double bottom = top + ellips.Height;
if (point.X < left) return HitType.None;
if (point.X > right) return HitType.None;
if (point.Y < top) return HitType.None;
if (point.Y > bottom) return HitType.None;
const double GAP = 10;
if (point.X - left < GAP)
{
if (point.Y - top < GAP) return HitType.UL;
if (bottom - point.Y < GAP) return HitType.LL;
return HitType.L;
}
if (right - point.X < GAP)
{
if (point.Y - top < GAP) return HitType.UR;
if (bottom - point.Y < GAP) return HitType.LR;
return HitType.R;
}
if (point.Y - top < GAP) return HitType.T;
if (bottom - point.Y < GAP) return HitType.B;
return HitType.Body;
}
private void SetMouseCursor()
{
Cursor desired_cursor = Cursors.Arrow;
switch (MouseHitType)
{
case HitType.None:
desired_cursor = Cursors.Arrow;
break;
case HitType.Body:
desired_cursor = Cursors.Hand;
break;
case HitType.UL:
case HitType.LR:
desired_cursor = Cursors.SizeNWSE;
break;
case HitType.LL:
case HitType.UR:
desired_cursor = Cursors.SizeNESW;
break;
case HitType.T:
case HitType.B:
desired_cursor = Cursors.SizeNS;
break;
case HitType.L:
case HitType.R:
desired_cursor = Cursors.SizeWE;
break;
}
if (Cursor != desired_cursor) { Cursor = desired_cursor; }
canvas.Cursor = desired_cursor;
}
private void canvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.Source is Ellipse)
{
elip = e.Source as Ellipse;
MouseHitType = SetHitType(elip, Mouse.GetPosition(canvas));
if (MouseHitType == HitType.None) return;
LastPoint = Mouse.GetPosition(canvas);
DragInProgress = true;
}
else
{
is_drawing = true;
anchorPoint = e.MouseDevice.GetPosition(canvas);
elip = new Ellipse
{
Stroke = Brushes.Black,
StrokeThickness = 2,
Fill = Brushes.Transparent
};
canvas.Children.Add(elip);
}
}
private void canvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (!DragInProgress)
{
MouseHitType = SetHitType(elip, Mouse.GetPosition(canvas));
SetMouseCursor();
if (!is_drawing)
return;
Point location = e.MouseDevice.GetPosition(canvas);
double minX = Math.Min(location.X, anchorPoint.X);
double minY = Math.Min(location.Y, anchorPoint.Y);
Double maxX = Math.Max(location.X, anchorPoint.X);
Double maxY = Math.Max(location.Y, anchorPoint.Y);
Canvas.SetTop(elip, minY);
Canvas.SetLeft(elip, minX);
double height = maxY - minY;
double width = maxX - minX;
elip.Height = Math.Abs(height);
elip.Width = Math.Abs(width);
}
else
{
Point point = Mouse.GetPosition(canvas);
double offset_x = point.X - LastPoint.X;
double offset_y = point.Y - LastPoint.Y;
double new_x = Canvas.GetLeft(elip);
double new_y = Canvas.GetTop(elip);
double new_width = elip.Width;
double new_height = elip.Height;
switch (MouseHitType)
{
case HitType.Body:
new_x += offset_x;
new_y += offset_y;
break;
case HitType.UL:
new_x += offset_x;
new_y += offset_y;
new_width -= offset_x;
new_height -= offset_y;
break;
case HitType.UR:
new_y += offset_y;
new_width += offset_x;
new_height -= offset_y;
break;
case HitType.LR:
new_width += offset_x;
new_height += offset_y;
break;
case HitType.LL:
new_x += offset_x;
new_width -= offset_x;
new_height += offset_y;
break;
case HitType.L:
new_x += offset_x;
new_width -= offset_x;
break;
case HitType.R:
new_width += offset_x;
break;
case HitType.B:
new_height += offset_y;
break;
case HitType.T:
new_y += offset_y;
new_height -= offset_y;
break;
}
if ((new_width > 0) && (new_height > 0))
{
Canvas.SetLeft(elip, new_x);
Canvas.SetTop(elip, new_y);
elip.Width = new_width;
elip.Height = new_height;
LastPoint = point;
}
}
}
private void canvas_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (DragInProgress)
DragInProgress = false;
if (is_drawing)
{
is_drawing = false;
elip.Stroke = Brushes.Black;
elip.StrokeThickness = 2;
elip.Fill = Brushes.Transparent;
}
}
我嘗試使用MVVM Framework達到相同的結果,但是它不起作用。
https://www.codeproject.com/Tips/478643/Mouse-Event-Commands-for-MVVM
上面的鏈接幫助我使用MVVM編寫了Mouse Event Commands,並且我使用相同的代碼進行了少量修改就可以實現結果,並且可以正常工作。
我的代碼中的更改是
在“代碼隱藏”中,我創建了一個Canvas元素,例如
Canvas canvas = new Canvas();
並在canvas_PreviewMouseDown方法中包含了一行代碼
if (e.OriginalSource is Canvas)
canvas = (Canvas)e.OriginalSource;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.