在WPF Canvas上选择对象?

时间:2009-02-23 17:24:25

标签: wpf select canvas

我有一个带有一些Ellipse对象的WPF Canvas(显示为圆圈)。每个圆都来自一个集合类实例,它实际上是一个自定义的孔模式类。每个模式都有一定数量的圆圈,然后使用下面的代码使用集合上的迭代将每个圆圈添加到画布。

因此,画布上填充了一堆圆圈,每个圆圈属于某个模式实例。您可以在此处看到屏幕截图:http://twitpic.com/1f2ci/full

现在我想添加点击画布上的圆圈的功能,并能够确定它所属的集合,这样我就可以对该圆所属的选定图案做更多的工作。< / p>

public void DrawHoles()
{
   // Iterate over each HolePattern in the HolePatterns collection... 
   foreach (HolePattern HolePattern in HolePatterns)
    {
        // Now iterate over each Hole in the HoleList of the current HolePattern...
        // This code adds the HoleEntity, HoleDecorator, and HoleLabel to the canvas
        foreach (Hole Hole in HolePattern.HoleList)
        {

            Hole.CanvasX = SketchX0 + (Hole.AbsX * _ZoomScale);
            Hole.CanvasY = SketchY0 - (Hole.AbsY * _ZoomScale);
            canvas1.Children.Add(Hole.HoleEntity);
        }
    }
}

3 个答案:

答案 0 :(得分:3)

所有FrameworkElements都有Tag属性,该属性属于object类型,可用于保存任意信息。您可以将HolePattern分配给Tag属性,稍后可以轻松使用该属性来获取相关集合。

即:

...
Hole.HoleEntity.Tag = HolePattern as object;
canvas1.Children.Add(Hole.HoleEntity);

稍后点击事件:

event(object sender,....)
{
   Ellipse e = sender as Ellipse;
   HolePattern hp = e.Tag as HolePattern;
   ...
}

答案 1 :(得分:0)

所以你可能已经阅读了我的回复,我说我有它的工作。它确实工作得很好(除了鼠标需要很高的精度),但我想问一下:将事件处理程序添加到添加到画布的每个椭圆是否真的很聪明?现在我不知道可能是什么样的内存bog,或者它可能是WPF和Windows处理的一块蛋糕。

在一个实际案例中,我猜即使在具有多种模式的屏幕上,也不会有更多的30-50个洞,但仍然存在; FIFTY 事件处理程序?这看起来很吓人。实际上,每个“洞”在视觉上由两个同心圆和一个文本标签表示(请参见此处的屏幕显示:http://twitpic.com/1f2ci/full),我知道用户希望能够点击其中任何一个元素到选择一个洞。这意味着每个洞的3个元素上的事件处理程序。现在我们可以谈论100个或更多事件处理程序。

似乎应该有一个解决方案,你可以在Canvas上只有一个事件处理程序,并在鼠标下读取元素引用,然后处理它以获取该元素的.Tag属性,依此类推。

答案 2 :(得分:0)

我认为我会发布我的最终和更精确的解决方案,以防它帮助其他任何人。

void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    int ClickMargin = 2;// Adjust here as desired. Span is in both directions of selected point.
    var ClickMarginPointList = new Collection<Point>();
    Point ClickedPoint = e.GetPosition(canvas1);
    Point ClickMarginPoint=new Point();
    for (int x = -1 * ClickMargin; x <= ClickMargin; x++)
    {
        for (int y = -1 * ClickMargin; y <= ClickMargin; y++)
        {
            ClickMarginPoint.X = ClickedPoint.X + x;
            ClickMarginPoint.Y = ClickedPoint.Y + y;
            ClickMarginPointList.Add(ClickMarginPoint);
        }
    }

    foreach (Point p in ClickMarginPointList)
    {
        HitTestResult SelectedCanvasItem = System.Windows.Media.VisualTreeHelper.HitTest(canvas1, p);
        if (SelectedCanvasItem.VisualHit.GetType().BaseType == typeof(Shape))
        {
            var SelectedShapeTag = SelectedCanvasItem.VisualHit.GetValue(Shape.TagProperty);
            if (SelectedShapeTag!=null &&  SelectedShapeTag.GetType().BaseType == typeof(Hole))
            {
                Hole SelectedHole = (Hole)SelectedShapeTag;
                SetActivePattern(SelectedHole.ParentPattern);
                SelectedHole.ParentPattern.CurrentHole = SelectedHole;
                return; //Get out, we're done.
            }
        }
    }
}