1

Here is the problem that has been with me for the past several days. I have 10000+ Line objects on a Canvas and a Slider that I use to scale the canvas to create a zoom effect. Everything is OK and the performance is great.

The only thing that bothers me is that the StrokeThickness of the Line gets scaled too. I tried to Bind the StrokeThickness to the inverse of the slider's value so that I get a uniform thickness whenever I move the slider. This worked but has decreased the performance substantially.

Is there any other way that would be suitable to this situation. I want to have a zero-width line thickness no matter how far I scale the canvas (like in CAD programs).

Vahid
  • 5,144
  • 13
  • 70
  • 146
  • Can you not move your `Slider` outside the `Canvas`? – Anchit Mar 20 '14 at 09:10
  • @Anchit My `Slider` is ouside the `Canvas` already. I use slider to Scale the `Canvas`. But the `StrokeThickness` of the `Line` objects on `Canvas` changes too! – Vahid Mar 20 '14 at 09:13
  • In that case, I believe there is no straight-forward way to do it. [Check This Link](http://stackoverflow.com/a/10127488) – Anchit Mar 20 '14 at 09:14
  • 1
    You're using `ScaleTransform` right? – Anchit Mar 20 '14 at 09:15
  • @Anchit Yes I'm using `ScaleTransform'. I'm wondering how CAD programs do this then. – Vahid Mar 20 '14 at 09:19
  • @Anchit I checked that link. I want all the Children of the Canvas to Scale. I just want to override the StrokeThickness property of the Line objects. – Vahid Mar 20 '14 at 09:21
  • It doesn't work that way, you see even if you set the `ScaleTransform` to `2.0`, the `StrokeThickness` of the `Line` remains the initial value only. The change happens to the final rendered view, values of individual properties are not changed. So, overriding the `StrokeThickness` doesn't really mean anything. – Anchit Mar 20 '14 at 09:34
  • Thanks, any suggestions on how can I keep the `StrokeThickness` unchanged for the `Lines` in the final rendered view? – Vahid Mar 20 '14 at 09:38
  • You might go for a somewhat different approach. Instead of putting Lines on the Canvas and scaling the whole Canvas, you may put Path elements with LineGeometries (in Path.Data) and only scale those geometries by their [Transform](http://msdn.microsoft.com/en-us/library/system.windows.media.geometry.transform(v=vs.110).aspx) property. – Clemens Mar 20 '14 at 10:01
  • @Clemens I tried this also. This approach also degrades the performance substantially. I have read an approach in this link that is completely similar to my problem but I couldn't figure it out [link](http://social.msdn.microsoft.com/Forums/vstudio/en-US/3a4b776a-5306-41f0-916e-0a0c174cd41f/wpf-invariant-does-not-scale-stroke-thickness?forum=wpf} – Vahid Mar 20 '14 at 10:05
  • Are all these lines vertical or horizontal? or can be angled as well? – Anchit Mar 20 '14 at 10:58
  • They can be angled as well. Another method was proposed by someone who said to extend the Line class and then add a method to it that inverses the StrokeThickness. I don't know if this is like the Binding approach I implemented an degrade the performance or it is different. It seems to have the same logic. http://social.msdn.microsoft.com/Forums/vstudio/en-US/3a4b776a-5306-41f0-916e-0a0c174cd41f/wpf-invariant-does-not-scale-stroke-thickness?forum=wpf – Vahid Mar 20 '14 at 11:04
  • From my understanding, I think it will have the same performance as of your binding solution. Just that you won't have to provide the binding for each and every line. Though I'd suggest you to try it, just to be sure. – Anchit Mar 20 '14 at 11:12
  • @Anchit The same low performance. Did you have any ideas when you asked about the lines being vertical? – Vahid Mar 20 '14 at 11:32
  • @Vahid Just in case all the lines don't need to be separate UI elements (e.g. for individual hit testing), you could add all their LineGeometries into one GeometryGroup and put that into a single Path control. Now you would have to update only the GeometryGroup's Transform property. – Clemens Mar 20 '14 at 11:40
  • @Clemens I tried the exact thing but it did have low performance for the scaling as well. – Vahid Mar 20 '14 at 11:41

1 Answers1

1

For the effect you want to achieve, overriding the StrokeThickness doesn't really mean anything as the it's value actually remains the same even if the ScaleTransform is changed.

The approach that you tried - Bind the StrokeThickness to the inverse of the slider's value - seems to be the most plausible one. To improve performance, instead of setting the StrokeThickness directly to inverse of Slider's value, set it to another property on your view model.

Then, in the event where sliding is completed, set the value of that property to the inverse of StrokeThickness.

Example -

private void OnSlidingComplete(object sender, EventArgs e)
{
    LineStrokeThickness = GetInverseOfZoomValue();
}

I know that this is not exactly a solution, rather a workaround.

Anchit
  • 548
  • 2
  • 8
  • 25
  • This won't work for the Slider's `ValueChanged` event. It will only work after I release the mouse on the slider. – Vahid Mar 20 '14 at 10:02
  • That's what I meant by the `OnSlidingComplete` event. See here - [WPF: Slider event that triggers after drag is complete](http://stackoverflow.com/a/723547/416236) – Anchit Mar 20 '14 at 10:06
  • I want to see the changes in real-time. Let's consider this possibility that instead of Slider I use Mouse wheel. – Vahid Mar 20 '14 at 10:09
  • The changes will be real-time, just that all the `Line` controls would appear to get normalized once the drag-drop of slider is complete. To handle all cases (like mouse wheel, click on slider, keyboard) see [this link](http://stackoverflow.com/a/1665843/416236). – Anchit Mar 20 '14 at 10:15
  • I get what you mean the problem is when I release the mouse there is lag before this gets updated. I guess this is a major caveat in WPF that the StrokeThickness of the Line gets scaled too which makes it unsuitable for CAD programs. – Vahid Mar 20 '14 at 10:20
  • Please see this link which is completely similar to my problem:http://social.msdn.microsoft.com/Forums/vstudio/en-US/3a4b776a-5306-41f0-916e-0a0c174cd41f/wpf-invariant-does-not-scale-stroke-thickness?forum=wpf – Vahid Mar 20 '14 at 10:20
  • From your link above, a possible solution is suggested - [using Geometry objects and applying MatrixTransform](http://stackoverflow.com/a/771711/416236) and [MatrixTransform for Geometry](http://msdn.microsoft.com/en-us/library/system.windows.media.geometry.transform.aspx), have you tried these? – Anchit Mar 20 '14 at 10:27
  • @Anchrit Actually I didn't understand it :( – Vahid Mar 20 '14 at 10:50