In WPF, can you hittest segments of a PathFigure? - wpf

I'm making a control that involves dragging pieces of a displayed element around. Since part of it is an arc, I have to use a PathFigure so I can use ArcSegments. I'd like to be able to know if the mouse is over a particular segment of the figure, but I don't see an obvious way to do this. Is it impossible or am I missing something?

the root Path object has the normal UI events for Mouse, instead of one Path with lots of Arcs you will need lots of Paths with an arc in each.

Related

Efficiently display multiple markers on WPF image

I need to display many markers on a WPF image. The markers can be lines, circles, squares, etc. and there can be several hundreds of them.
Both the image source and the markers data are updated every few seconds. The markers are associated with specific pixels on the image and their size should be absolute in relation to the screen (i.e. when I move the image the markers should move along with it, but if i zoom in, they should take the same space of the screen as before).
Currently, I've implemented this using the AdornerLayer. This solution has several problems but the most significant one is that the UI doesn't fare well under the load even for 120 such markers.
I wanted to ask what would be the best way to go about implementing this? I thought of two solutions:
Inherit from Canvas and make sure it is invalidated not for every
added marker but for a range of markers at once
Create a control that holds an image and change its OnDraw to draw all the markers
I would appreciate some pointers from someone with experience with a similar problem.
Your use case looks quite specialized, so a specialized solution seems in order. I'd try a variant of your second option — extend Image, overriding its OnRender method.

Canvas - dynamic drawing and managing shapes

I'm trying to make an application which allows the user to draw shapes to the canvas. Once drawn, I would like for the user to be able to select, move, resize, basically manipulate the shapes in any which way.
I have done something similar in XNA and that was quite easy due to the fact that there was a draw loop. In Silverlight there is no such thing as far as I understand and I am having trouble figuring out how to manage the objects on the canvas. As in what is the best way to manage the canvas' children collection to ensure appropriate response of the UI to what the user does.
Most examples out there are pretty basic and do not go anywhere near this kind of thing. I would be grateful if somebody who has done this before could tell me how they approached the problem.
Thinking about it for a while I think I figured out how it works.
There is a draw loop for the canvas, which is the draw loop of the top level parent container which it lives on.
The difference with XNA I guess is that the collection of items to draw on the canvas doesn't need to be explicitly drawn, since the canvas takes care of drawing its children automatically.
So, what I need is some way to hold on to any object I add to the canvas' children... I can then update the objects drawing properties and the changes will be reflected in the canvas next time it refreshes.
I guess a dictionary of some sort in which to store the items I put in the list might be best...?
Not a finished answer yet, but I guess I understand half of it now.

How can you do custom drawing but with a mask?

We have a control which we do our own custom drawing in OnRender. However, we would like to use a PNG with transparency as sort of a stencil for various drawing 'passes' if you will.
Now we already know that we can simply use a PNG in an ImageBrush and set it as the control's OpacityMask, but we actually want to do several drawing passes with several different stencils. If we wanted to go the OpacityMask route, we'd have to create separate controls, separate ImageMasks, then stack them all up on top of each other which also clutters up your visual tree.
We don't want to do that. We want to do all of the drawing in the OnRender override of a single Control subclass. We just want those draw calls to be masked out by an image. We then want to repeat that over and over until our drawing is done.
Any way this can be done?
HA! Found it! Odd that the S/O community has been so quiet on this one, but for those looking for it, it's called DrawingContext.PushOpacityMask (and the corresponding 'Pop()') and does exactly what you think it does... it pushes an opacity mask (via a brush) onto the DC and all subsequent drawing is relative to the brush's opacity values.
You can also layer 'masks' for some pretty cool effects too. They are additive, not just the last one set.
I'm pretty sure the built-in OpacityMask is just used with this function in the OnRender call. What this means is you can still use the OpacityMask (provided you push that on first) then your own mask(s) for your own drawing calls. Pretty neat stuff!
Hope this helps others who were looking for this.

Clipping WPF elements in a canvas

I am working on an interactive WPF graph/tree tool and have nodes and links between them placed in a canvas. The nodes are usercontrols and the links are simply Line shapes, and currently the links go from the centre of a node to another node's centre.
The problem arise when I want the nodes to be slightly transparent and one sees the links behind the nodes.
I figured the most convenient solution would be to apply clipping or opacitymask to the lines, so they are not drawn behind the nodes, but I can't for the life of me figure out how?
Basically I can't figure out a bounding box geometry from the nodes to use as a clipping geometry for the lines. I am also interested in alternative solutions, of course!
It would seem to me like you're overthinking the solution. Why not just change the logic for the links so that the lines begin/end at the correct side of the node instead of starting from the center??? You should only need to do a little more math to accomplish this.
That said, to get the bounding box of a Visual you can use the VisualTreeHelper::GetContentBounnds helper method.
The VisualTreeHelper.GetContentBounds() method seems to return Empty everytime.
An alternative solution to this problem is answered at
Connecting two WPF canvas elements by a line, without using anchors?
that uses bounding boxes to find intersection points to draw the lines from/to.
We worked on something similar and our solution was to put links and nodes on different layers.
So if you want the nodes to appear above the links and the tips of the links to be hidden by the nodes, you just change the z-order of the layers so that the nodes layer is in front of the links-layer.
As layers we used VisualHosts (you find a VisualHost class here) an our node and link objects were DrawingVisuals.
Works fine and you don't need to hassle about finding the borders of your nodes etc.

WPF Grid Question, can I determinate the absolute position of something, which is positioned automatically in a WPF Grid?

I like to use a grid to position some objects in WPF, because it cares about the position and stuff. In addition, however I also like to be able to draw accross the cells with a Canvas.
I figured out that this can be done by embedding the grid in a canvas. However in order to connect two elements, I need then the absolute position in pixels.. any ideas?
From code you can use the UIElement.TranslatePoint() method.

Resources