By default, when manipulating a ScatterViewItem control it will rotate about its own center point.
Is there any way to alter this such that the control rotates about another point, for example rotate about its own top left corner?
I don't think this is supported by the ScatterViewItem control. Technically I think it's just adjusting the rendertransform as it's being manipulated, but a simple test of altering that didn't seem to work. It's likely resetting it at runtime. Not sure why you need this functionality (it seems like it wouldn't feel very natural), but I'd recommend creating a custom control to do it.
Related
So there's this tutorial about creating a diagram in WPF.
http://www.codeproject.com/Articles/24681/WPF-Diagram-Designer-Part
I've read it, and still studying it to understand it completely.
At the end of this tutorial, you can basically add shapes, move/rotate/scale them, and since they are created in a vector form, they are keeping their resolutions, there are also connectors that can connect each shape with another.
My goal, since I need to create a simulator which shows how internet protocols are delivered, is to create a divided diagram in which Side A communicates with Side B. it could read an automata and simulate the transitions in the diagram.
I'm thinking of how to deliever this, and since I don't have a lot of knowledge in WPF, I wonder in which way should I implement it.
Should I create 2 different Canvases? or maybe dividing 1 canvas with two sides?
The main issue I'm dealing with, is that when a shape is being dragged to the end margin of the window, then the window allow me to slide it so I can see the rest of the field, this is being done by increasing the size of the Canvas, as seen in the Tutorial Part 1.
However, if my canvas is divided by two, and there's a border in the middle, how can I create two sliders for each of the sides?
I was wondering if you can give me any tips about how approaching this idea, since my knowledge in WPF is still very limited.
Here is my point of view, but it would be very useful if you would provide a more/less final sketch of your app. I recommend using Telerik AppMock but paint will also suffice ;).
From what I have understood you should need 3 canvases.
1-st is canvas on the left.
2-nd is canvas on the right.
3-rd is on top of both canvases.
When you want to drag an element, you must set opacity of the clicked element to be a bit transparent and leave it on its place(1st canvas), add copy of dragged element in to the 3rd canvas. When you do leftmousebuttonup(drop dragged item), you have to check where was it dropped and if it was droppend on the 2nd canvas you add it to this canvas. To position element on the canvas you can use Canvas.SetLeft and accordingly SetRight method.
You can put 1st and 2nd canvases into Grid. Even if Canvases will be bigger if Grid, view will be cut only to the size of the Grid.
Moreover, to allow canvases manipulation, add there (to the Grid) a scrollviewer which will Translate Transform the canvases given to their sizes.
Later, try to use MVVM pattern to fill your Canvases with data.
I would also suggest an ObservableColletion of drawable (you can use FrameworkElement as base class) and draggable objects. Different for every Canvas.
Good luck!
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.
So I realize that I am venturing outside of the intended use of a Canvas here and will likely have to come up with a more manual solution. However, not being overly experienced in WPF I was hoping that there may be some solution which would allow me to continue using a Canvas control and the features it gives you for free.
The issue revolves around a Canvas which is used to zoom in and out of an image and some number of child controls that belong to the Canvas. These child controls are to be placed at various positions on the image and, as such, the Canvas works nicely in that it handles all of the layout/positioning for me as I zoom in or out.
However, one drawback is that the Canvas scales these child controls up as I zoom into the image, causing them to become too large to be usable in practice. What I am looking for is a solution that allows me to zoom into an image that belongs to a canvas without also zooming up the size of the child controls, preferably handling the layout for me.
I have tried modifying the width and height of these child controls as the zoom factor increases or decreases, but there is a slight lag time and it all looks a bit 'jerky'.
If it comes down to it I will simply do all of the zooming/panning/layout myself, but I thought I would ask first just to make sure that I am not missing anything that would allow me to tell the Canvas to not scale the size of certain controls. Thanks in advance.
You can bind the children's RenderTransform to the inverse of the Canvas' transform, see my answer to this similar question on rotation.
This is more of a thought than an answer, but what if you set a transform on the element that you did not want scaled that was the opposite of the canvas itself. So for example, if the canvas had a scale transform of 2.0, set the element to have a scale transform of 0.5. You could probably accomplish this by binding the transform values together using a value converter.
You'll probably want to make sure the element has a render transform origin of 0.5,0.5 so that it scales from the center.
I'm currently creating a MSPaint-like WPF-application and struggling with the implementation of a snappable grid.
The painting of the grid is no problem with a VisualBrush and a Rectangle but the problem is that these lines are then purely for looks and can't be easily changed (for example highlighted when the snapping to a specific line triggered).
My other idea was to have a 2 Canvas solution where 1 Canvas is used for the elements and one Canvas (who is positioned above the other) contains all the grid lines. However I have the feeling that this would mean quite a performance hit.
Are there any other possible ways to implement this kind of functionality?
Efficiency considerations of a two-panel approach vs DrawingContext
I have good news for you: You are wrong about the significant performance hit. Your two-canvas idea is nearly optimal, even if you use individual objects for the grid lines. This is because WPF uses retained-mode rendering: When you create the canvas, everything on it is serialized into a compact structure at native level. This only changes when you change the grid lines in some way, such as changing the grid spacing. At all other times the performance will be indistinguishable from the very fastest possible managed-code methods.
A slight performance increase could be had by using DrawingContext as Nicholas describes.
A simpler and more efficient solution
Perhaps a better way then drawing individual lines on the grid canvas is to use two tiled visual brushes (one horizontal, one vertical) to draw all unhilighted lines, then use Rectangle(s) added in code-behind to hilight the line(s) you are snapping to.
The main advantage of this technique is that your grid can be effectively infinite, so there is no need to calculate the right number of grid lines to draw and then update this every time the window resizes or the zoom changes. You also only have three UIElements involved, plus one more for each grid line that is currently hilighted. It also seems cleaner to me than tracking collections of grid lines.
The reason you want to use two visual brushes is that drawing is more efficient: The brush drawing the vertical lines is stretched to a huge distance (eg double.MaxValue/2) in the vertical direction so the GPU gets only one drawing call per vertical line, the same for the horizontal. Doing a two-way tiling is much less efficient.
Adorner layer
Since you asked about alternatives, another possibility is to use Adorner and AdornerLayer with any of the solutions above rather than stacking your canvas using eg a Grid or containing Canvas. For a Paint-like application this is nice because the adorner layer can be above your graphic layer(s) yet the adorners can still attach to individual items that are being displayed.
You might consider drawing your grid using the DrawingContext inside of OnRender. Drawing this way does not introduce new UIElements into the visual tree, which helps to keep performance up. In some ways, it is similar to what you are currently doing with the VisualBrush, which also does not create new UI elements per copy.
However, since you will actually be individually drawing each line instead of copying the look of a single line, you'll be able to highlight the grid line(s) that participate in snapping without changing the colors of those that do not.
If you are going to go down this route, make sure to have a look into GuidelineSets for positioning your guide lines (more details here), since you'll probably want to have your guide lines snap to the device's pixels so that they draw sharply.
I have an app with a bunch of controls in it and I want to place a set of cross hairs on top of it. My first attack used a PictureBox and ran into this problem. The solution that fellow proposes, seems a bit... verbose for what I need.
Is there a simple way draw on top of my form? Note that I don't even need the drawing to be part of a control as it doesn't need to do anything but just be there.
This eventually worked. I had to play some games though because most of the controls I wanted to draw on were not where it expected them to be.
Also, it ran into issues when controls were moved; it failed to redraw and stuff moved with the underlying control. This was fixed by forcing invalidation from the move event for anything that might move.
Does a PictureBox with a transparent image have the same problem as a Panel with BackColor set to Transparent? I'm thinking you could have a PictureBox with the crosshair image in it and move that around, instead of drawing it yourself...