WPF canvas locate
//xaml <Window x:Class="WpfApp210.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:WpfApp210" mc:Ignorable="d" WindowState="Maximized" Title="{Binding LocatedPt,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="450" Width="800"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="200"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <DataGrid Grid.Column="0" x:Name="dg" ItemsSource="{Binding BooksList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionChanged="dg_SelectionChanged" /> <Canvas Grid.Column="1" x:Name="cvs" ClipToBounds="True"/> </Grid> </Window> //cs using System; using System.Collections.Generic; using System.Collections.ObjectModel; 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.Navigation; using System.Windows.Shapes; namespace WpfApp210 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window, INotifyPropertyChanged { public MainWindow() { InitializeComponent(); this.Loaded += MainWindow_Loaded; this.DataContext = this; } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propName) { var handler = PropertyChanged; if (handler != null) { handler?.Invoke(this, new PropertyChangedEventArgs(propName)); } } private ObservableCollection<Book> booksList; public ObservableCollection<Book> BooksList { get { return booksList; } set { if (value != booksList) { booksList = value; OnPropertyChanged(nameof(BooksList)); } } } private string locatedPt; public string LocatedPt { get { return locatedPt; } set { if(value!= locatedPt) { locatedPt = value; OnPropertyChanged(nameof(LocatedPt)); } } } Ellipse markedElp { get; set; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { double width = this.ActualWidth-200; double height = this.ActualHeight; Random rnd = new Random(); BooksList = new ObservableCollection<Book>(); for (int i = 0; i < 200; i++) { int ptX = rnd.Next(0, (int)width - 30); int ptY = rnd.Next(0, (int)height - 30); BooksList.Add(new Book() { Id = i + 1, Name = $"Name_{i + 1}", Pt = new Point(ptX, ptY) }); Ellipse elp = new Ellipse(); elp.Width = 30; elp.Height = 30; elp.StrokeThickness = 5; elp.Stroke = new SolidColorBrush(Colors.Cyan); //elp.Fill = new SolidColorBrush(Colors.Cyan); Canvas.SetLeft(elp, ptX); Canvas.SetTop(elp, ptY); cvs.Children.Add(elp); } markedElp = new Ellipse(); markedElp.Width = 50; markedElp.Height = 50; markedElp.Stroke = new SolidColorBrush(Colors.Red); markedElp.StrokeThickness = 15; markedElp.Fill = new SolidColorBrush(Colors.Transparent); } private void DrawEllipses() { } private void dg_SelectionChanged(object sender, SelectionChangedEventArgs e) { if(dg.SelectedItem!=null) { var bk=dg.SelectedItem as Book; if(bk!=null) { Canvas.SetLeft(markedElp, bk.Pt.X-10); Canvas.SetTop(markedElp, bk.Pt.Y-10); if(cvs.Children.Contains(markedElp)) { cvs.Children.Remove(markedElp); } cvs.Children.Add(markedElp); LocatedPt = $"({bk.Pt.X},{bk.Pt.Y})"; } } } } public class Book { public int Id { get; set; } public string Name { get; set; } public Point Pt { get; set; } } }