私はそれをやったと思います(私を始めるのを手伝ってください)...
まず、移動イベントの処理を各 Ellipse ではなく Canvas に移動しました。OOPの観点からは、それは良いことでも悪いことでもあります。少なくとも、マウス イベントの処理が各ホール (ホールのビジュアルである楕円) に設定するホールパターンの責任である場合は、HolePattern の消費者がこの機能を自動的に取得できるように抽象化されます。ただし、メインの UI コードに移動することで、キャンバス マウス イベントをより高いレベルで処理できるようになりました。しかし、それも悪いことばかりではありません。この部分については何日も話し合うことができます。
ポイントは、マウスでキャンバス上で何かを選択し、選択した楕円が属する穴を読み取るときに「誤差の範囲」を作成する方法を設計したことです。次に、穴が属するHolePatternを読み取ることができますに、UI 全体 (ListView、テキストボックス、座標のグリッドビュー) はすべて既存の XAML バインディングによって更新され、キャンバスは既存のメソッドを 1 回呼び出してキャンバスを再生成することで更新されます。
正直に言うと、(もちろん、あなたの助けや他の人たちの助けもありましたが) すべてを理解できたとは信じられません。これのビジョンを持ち、それが実現するのを見るのはとてもクールな気持ちです。
ここでメインコードをチェックしてください:
void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
int ClickMargin = 2;
Point ClickedPoint = e.GetPosition(canvas1);
Point p1 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y - ClickMargin);
Point p2 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y + ClickMargin);
Point p3 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y + ClickMargin);
Point p4 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y - ClickMargin);
var PointPickList = new Collection<Point>();
PointPickList.Add(ClickedPoint);
PointPickList.Add(p1);
PointPickList.Add(p2);
PointPickList.Add(p3);
PointPickList.Add(p4);
foreach (Point p in PointPickList)
{
HitTestResult SelectedCanvasItem = System.Windows.Media.VisualTreeHelper.HitTest(canvas1, p);
if (SelectedCanvasItem.VisualHit.GetType() == typeof(Ellipse))
{
var SelectedEllipseTag = SelectedCanvasItem.VisualHit.GetValue(Ellipse.TagProperty);
if (SelectedEllipseTag!=null && SelectedEllipseTag.GetType().BaseType == typeof(Hole))
{
Hole SelectedHole = (Hole)SelectedEllipseTag;
SetActivePattern(SelectedHole.ParentPattern);
SelectedHole.ParentPattern.CurrentHole = SelectedHole;
}
}
}
}