好,首先我覺得你的方式做到這一點是easyest之一。但是你讓我感興趣,我探索了另一種選擇元素的方法。當然可能需要很多工作來調整它,但也許會讓你走上另一種方式。
我的想法是基於。它會在您指出的點執行命中測試,並返回在該點中找到的依賴對象。所以我所做的就是聽MouseRightButtonDown事件(在我的例子中是在一個Window中),並且從按下鼠標右鍵的點開始,我計算一個形成圓形網格的點的網格。然後我HitTest每個點,如果我找到一個已知的命名路徑,我可以安全地選擇它。
此(太長了)的解釋後,來了一個示例代碼:
List<DependencyObject> hitResultsList = new List<DependencyObject>();
private void WrapPanel_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Window wp = sender as Window;
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);
bool elementFound = false;
foreach (Point point in GetPointsInCircle(pt, 8, pt, new Point(2, 2)))
{
// Clear the contents of the list used for hit test results.
Debug.Print(point.ToString());
hitResultsList.Clear();
// Set up a callback to receive the hit test result enumeration.
VisualTreeHelper.HitTest(wp, null,
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(point));
// Perform actions on the hit test results list.
foreach (DependencyObject d in hitResultsList)
{
if (d is Path)
{
Path p = d as Path;
if (p.Name == "link1")
{
elementFound = true; //Here we found the Path with name link1, we could then select it
break;
}
}
}
if (elementFound) break;
}
}
MyHitTestResult:
// Return the result of the hit test to the callback.
public HitTestResultBehavior MyHitTestResult(HitTestResult result)
{
// Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit);
// Set the behavior to return visuals at all z-order levels.
return HitTestResultBehavior.Continue;
}
GetPointsInCircle(獲取點的圓形網格):
private static IEnumerable<Point> GetPointsInCircle(Point circleCenter, float radius, Point gridCenter, Point gridStep)
{
if (radius <= 0)
{
throw new ArgumentOutOfRangeException("radius", "Argument must be positive.");
}
if (gridStep.X <= 0 || gridStep.Y <= 0)
{
throw new ArgumentOutOfRangeException("gridStep", "Argument must contain positive components only.");
}
// Loop bounds for X dimension:
int i1 = (int)Math.Ceiling((circleCenter.X - gridCenter.X - radius)/gridStep.X);
int i2 = (int)Math.Floor((circleCenter.X - gridCenter.X + radius)/gridStep.X);
// Constant square of the radius:
float radius2 = radius * radius;
for (int i = i1; i <= i2; i++)
{
// X-coordinate for the points of the i-th circle segment:
double x = gridCenter.X + i * gridStep.X;
// Local radius of the circle segment (half-length of chord) calulated in 3 steps.
// Step 1. Offset of the (x, *) from the (circleCenter.x, *):
double localRadius = circleCenter.X - x;
// Step 2. Square of it:
localRadius *= localRadius;
// Step 3. Local radius of the circle segment:
localRadius = (float)Math.Sqrt(radius2 - localRadius);
// Loop bounds for Y dimension:
int j1 = (int)Math.Ceiling((circleCenter.Y - gridCenter.Y - localRadius)/gridStep.Y);
int j2 = (int)Math.Floor((circleCenter.Y - gridCenter.Y + localRadius)/gridStep.Y);
for (int j = j1; j <= j2; j++)
{
yield return new Point(x, gridCenter.Y + j * gridStep.Y);
}
}
}
參考文獻:
HitTest on MSDN
Get all points on a uniform discrete grid inside a circle's radius (Adapted)
你有很多測試掩蓋了實際問題:你真正的問題是什麼?「我如何點擊曲線並將其註冊爲點擊」? –