Question

I have a custom element class that is a subclass of FrameworkElement.

public class MyCustomElement : FrameworkElement
{
    private VisualCollection children;

    public MyCustomElement()
    {
        this.children = new VisualCollection(this);
        this.children.Add(MyDrawingRoutines());
    }

    private DrawingVisual MyDrawingRoutines()
    {
        //...
    }

    protected override int VisualChildrenCount
    {
        get { return children.Count; }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= children.Count)
        {
            throw new ArgumentOutOfRangeException();
        }

        return children[index];
    }
}

The UI holds a canvas in which these custom drawing elements are added and hit testing is performed.

public partial class MainWindow : Window
{
        private MyCustomElement myCustomElement;

        public MainWindow()
        {
            InitializeComponent();

            myCustomElement = new MyCustomElement();
            myCanvas.Children.Add(myCustomElement);
        }

        private void myCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            System.Windows.Point pt = e.GetPosition((UIElement)sender);
            VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(leftClickCallback), new PointHitTestParameters(pt));
        }

        public HitTestResultBehavior leftClickCallback(HitTestResult result)
        {
            if (result.VisualHit.GetType() == typeof(DrawingVisual))
            {
                if (((DrawingVisual)result.VisualHit).Opacity == 1.0)
                {
                    ((DrawingVisual)result.VisualHit).Opacity = 0.4;
                }
                else
                {
                    ((DrawingVisual)result.VisualHit).Opacity = 1.0;
                }
            }

            return HitTestResultBehavior.Stop;
        }

    }
}

This code works as expected, but I cannot find a way to determine which MyCustomElement the detected DrawingVisual belongs. Right now, the opacity adjustment is done only superficially correct? I would like to change the opacity property on MyCustomElement, have the MyDrawingRoutines() method apply it, and have only the finished DrawingVisual drawn on the Canvas.

Was it helpful?

Solution

You should be able to cast the Parent property of the DrawingVisual to your MyCustomElement class:

public HitTestResultBehavior leftClickCallback(HitTestResult result)
{
    var visual = result.VisualHit as DrawingVisual;

    if (visual != null)
    {
        var element = visual.Parent as MyCustomElement;

        if (element != null)
        {
            if (element.Opacity == 1.0)
            {
                element.Opacity = 0.4;
            }
            else
            {
                element.Opacity = 1.0;
            }
        }
    }

    return HitTestResultBehavior.Stop;
}

In case you need to get the parent of any visual (not just a ContainerVisual, which has the Parent property as shown above), you may use VisualTreeHelper.GetParent:

var visual = result.VisualHit;
var element = VisualTreeHelper.GetParent(visual) as MyCustomElement;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top