//xaml
<Window x:Class="WpfApp58.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:behavior="http://schemas.microsoft.com/xaml/behaviors"
WindowState="Maximized"
xmlns:local="clr-namespace:WpfApp58"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<behavior:Interaction.Triggers>
<behavior:EventTrigger EventName="Closed">
<behavior:InvokeCommandAction Command="{Binding CloseWindowCommand}"/>
</behavior:EventTrigger>
</behavior:Interaction.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Canvas Grid.Row="0" x:Name="cvs"
Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
>
<behavior:Interaction.Triggers>
<behavior:EventTrigger EventName="MouseDown">
<behavior:InvokeCommandAction Command="{Binding MouseDownCommand}"
PassEventArgsToCommand="True"/>
</behavior:EventTrigger>
<behavior:EventTrigger EventName="MouseUp">
<behavior:InvokeCommandAction Command="{Binding MouseUpCommand}"
PassEventArgsToCommand="True"/>
</behavior:EventTrigger>
<behavior:EventTrigger EventName="MouseMove">
<behavior:InvokeCommandAction Command="{Binding MouseMoveCommand}"
PassEventArgsToCommand="True"/>
</behavior:EventTrigger>
</behavior:Interaction.Triggers>
</Canvas>
<StatusBar Grid.Row="1">
<StatusBarItem>
<TextBlock Text="{Binding StatusStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="20"/>
</StatusBarItem>
</StatusBar>
</Grid>
</Window>
//cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfApp58
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new CanvasVM(cvs);
this.DataContext = vm;
}
private void cvs_MouseDown(object sender, MouseButtonEventArgs e)
{
}
private void cvs_MouseUp(object sender, MouseButtonEventArgs e)
{
}
private void cvs_MouseMove(object sender, MouseEventArgs e)
{
}
}
public class CanvasVM : INotifyPropertyChanged
{
Canvas cvs;
Random rnd { get; set; }
Ellipse elp { get; set; }
double width, height;
private bool isMoving = false;
private bool isCopy = false;
private int idx = 0;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
private string statusStr;
public string StatusStr
{
get
{
return statusStr;
}
set
{
if (value != statusStr)
{
statusStr = value;
OnPropertyChanged(nameof(StatusStr));
}
}
}
private Ellipse capturedElp { get; set; }
public CanvasVM(Canvas cvsValue)
{
cvs = cvsValue;
InitData();
InitCommands();
}
private void InitData()
{
width = cvs.ActualWidth;
height = cvs.ActualHeight;
rnd = new Random();
elp = new Ellipse();
elp.Width = 100;
elp.Height = 100;
elp.ToolTip = ++idx;
elp.Stroke = new SolidColorBrush(Colors.Blue);
elp.Fill = new SolidColorBrush(Colors.Red);
elp.StrokeThickness = 5;
Canvas.SetLeft(elp, rnd.Next(0, (int)width));
Canvas.SetTop(elp, rnd.Next(0, (int)height));
if (!cvs.Children.Contains(elp))
{
cvs.Children.Add(elp);
}
}
private void InitCommands()
{
MouseDownCommand = new DelCommand(MouseDownCommandExecuted);
MouseUpCommand = new DelCommand(MouseUpCommandExecuted);
MouseMoveCommand = new DelCommand(MouseMoveCommandExecuted);
CloseWindowCommand = new DelCommand(CloseWindowCommandExecuted);
}
private void CloseWindowCommandExecuted(object obj)
{
var msgResult = MessageBox.Show("Are you sure to exit?", "Exit", MessageBoxButton.YesNo,
MessageBoxImage.Information, MessageBoxResult.Yes);
if (msgResult == MessageBoxResult.Yes)
{
Application.Current?.Shutdown();
}
}
private void MouseMoveCommandExecuted(object obj)
{
var e = obj as MouseEventArgs;
var pt = e.GetPosition(cvs);
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
StatusStr = $"{pt.X},{pt.Y}";
}));
if (e == null)
{
return;
}
if (Keyboard.Modifiers == ModifierKeys.Control && Keyboard.IsKeyDown(Key.C) && Mouse.LeftButton == MouseButtonState.Pressed)
{
isCopy = true;
}
else if(Keyboard.Modifiers == ModifierKeys.Control && Mouse.LeftButton==MouseButtonState.Released)
{
capturedElp = Mouse.Captured as Ellipse;
isMoving = true;
}
e.Handled = true;
}
private void MouseUpCommandExecuted(object obj)
{
var e = obj as MouseButtonEventArgs;
if (e == null)
{
return;
}
var pt = e.GetPosition(cvs);
if (Keyboard.Modifiers == ModifierKeys.Control && Mouse.LeftButton == MouseButtonState.Released
&& isCopy)
{
Ellipse elp = new Ellipse();
elp.Width = 100;
elp.Height = 100;
elp.ToolTip = ++idx;
elp.Stroke = new SolidColorBrush(Colors.Blue);
elp.Fill = new SolidColorBrush(Colors.Red);
elp.StrokeThickness = 5;
Canvas.SetLeft(elp, pt.X);
Canvas.SetTop(elp, pt.Y);
if (!cvs.Children.Contains(elp))
{
cvs.Children.Add(elp);
}
isCopy = false;
}
if (isMoving)
{
if (capturedElp != null && isMoving)
{
Canvas.SetLeft(capturedElp, pt.X);
Canvas.SetTop(capturedElp, pt.Y);
}
isMoving = false;
}
e.Handled = true;
}
private void MouseDownCommandExecuted(object obj)
{
var e = obj as MouseEventArgs;
cvs.CaptureMouse();
Mouse.Capture(elp);
e.Handled = true;
}
public DelCommand MouseDownCommand { get; set; }
public DelCommand MouseUpCommand { get; set; }
public DelCommand MouseMoveCommand { get; set; }
public DelCommand CloseWindowCommand { get; set; }
public List<Visual> FindVisualChildren(DependencyObject dpObj)
{
List<Visual> childrenList = new List<Visual>();
int childrenCount = VisualTreeHelper.GetChildrenCount(dpObj);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(dpObj, i) as Visual;
if (child != null)
{
childrenList.Add(child);
childrenList.AddRange(FindVisualChildren(child));
}
}
return childrenList;
}
}
public class DelCommand : ICommand
{
private Action<object> execute;
private Predicate<object> canExecute;
public DelCommand(Action<object> executeValue, Predicate<object> canExecuteValue = null)
{
this.execute = executeValue;
this.canExecute = canExecuteValue;
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object parameter)
{
if (canExecute == null)
{
return true;
}
return canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
}
}
![]()
![]()