Using SnapsToDevicePixels in OnRender - wpf

I have a class derived from FrameworkElement in which I override the OnRender method to draw several lines. I would like the behaviour of SnapsToDevicePixels to work with my primitive control, what is the best way to go about doing this?.
I am aware of GuidelineSets and how to use them, but looking at some examples of elements over at .NET Reference Source they were not used and I saw nothing that takes into account SnapsToDevicePixels in the OnRender overrides. Only a few portions of UIElement does anything with it in the Arrange method, yet the property works on Rectangles.
I feel as though checking the SnapsToDevicePixels property is true and then pushing a GuidelineSet onto the drawingContext would be the naïve approach and I had thought (hoped) there was a better way to incorporate it.
Is this the case? If so, How should I design my OnRender methods to utilise SnapsToDevicePixels?

Related

From GDI to WPF: rendering

In GDI you just use System.Drawing.Graphics to manually handle the rendering.
In WPF is DrawingContext the way to go?
https://msdn.microsoft.com/en-us/library/system.windows.media.drawingcontext(v=vs.110).aspx
You could indeed override the OnRender method of a UIElement to define your own rendering instructions but note that this is not an immediate mode rendering API like Windows Forms's OnPaint. In fact there is no such API available in WPF.
The drawing operations of the DrawingContext are not used directly when the OnRender method is invoked. They are instead processed by the rendering thread at a later stage.
So depending on what you are trying to do, overriding the OnRender method may not be your best choice after all. You may want to stick to the "WPF way" of creating composite UI elements.

How to avoid WPF to make Arrangements/Measurements on my own controls?

I have developed a 3D-engine in C# and I want it to be usable from within a WPF application through classes that can be used just like any other WPF Control.
First implementation
I created a Panel (let's call it EnginePanel) that extends the Grid class, and a set of controls to put inside like SceneNodeControl, GeometryControl, etc... These controls inherit the FrameworkElement WPF class.
For the SceneNodeControl, I exposed a Children property (UIElementCollection) and overrode that Logical/Visual management methods so that they look inside this collection.
I also overrode the ArrangeOverride and MeasureOverride methods so that we call Arrange/Measure on each child of the SceneNodeControl and then return a constant Size of zero pixels.
This implementation works and allows me to use ItemsControl, ContentControl and DataTemplates to populate my scene graph with a classical MVVM pattern.
Problem
My problem is that if I create a massive scene graph with hundreds of SceneNodeControls, the application dramatically slows down.
A quick check with the Visual Studio Profiler informed me that the Measure method from SceneNodeControl is responsible for 80% to 90% of the CPU usage (in terms of time spent).
OK, no problem. What I have to do is to remove these calculations that are too heavy and moreover useless in my case.
Solution 1
I tried to simply remove the call to the Arrange/Measure methods on the children of the SceneNodeControl.
This does not work. As specified in MSDN, the implementations of these methods MUST call the Arrange/Measure on the children.
Solution 2
Inherits the FrameworkContentElement. Indeed, this class does not have layouting algorithms.
But it does not have any Visual tree management, which makes it unusable with ItemsControls, ContentControl and DataTemplates.
Other solutions
I don't have other solutions... so this is why I'm here now!
The question is How to avoid WPF to make Arrangements/Measurements on my own controls?
Thanks!
Edit
Solution 3
I found another solution to my problem (but it produces more and more questions).
My controls can inherit the DependencyObject class. In that way, it should be possible to use the DataContextes from other WPF controls and more generally their DependencyProperties.
Problem number 1: I cannot use the existing DataTemplate, ItemsControl and ContentControl classes, but I probably can reimplement them...
Problem number 2: I cannot tell a DependencyObject to be a 'parent' of another DependencyObject. I found some hacks that 'reflect' this class and expose hidden members to try to manage the InheritanceContext and InheritanceParent. But since no one seems to do that and since Microsoft obviously don't want us to use it, it's really hard...
I will probably open a new question about this second problem. (Edit: It's here.)
Edit: to focus my question
What I want is writing something like that:
<controls:SceneNodeControl NodeName="Root">
<ItemsControl ItemsSource="{Binding SceneNodes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:SceneNodeViewModel}">
<controls:SceneNodeControl NodeName="{Binding Name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</controls:SceneNodeControl>
and, at runtime, don't execute Measure/Arrange algorithms on the SceneNodeControls but build their Logical/Visual trees.
And here is my little test project.
If you don't want measure and Arrange affect the logic tree starting in NodeSceneControl and don't want to render it, just set its Visibility property to Visibility.Collapsed. This way, this node will be left out of the layout processing.

Is there any convinient way that i can deepclone 'style' instance in silverlight?

if a style is used, it can not be modified agaign. so i need a clone method. but its hard to implement.
what i want to do is implementing a cascading 'style' mechanism. for example, i set two style to the same frameworkelement. the same property of latter style will override the former one, while the different property remain unchanged.
but if i set the style property of the frameworkelement twice directly, the 1st style will be gone. so i use the baseon property of style class to do that. but now come across another problem, the style can not be modified after it's been set to a frameworkelement.
so now i need a clone method.
Kevin,
I have written a CloneObject class which is exactly what you are looking for. Check out my code here:
"Generic class for deep clone of Silverlight and C# objects".
Jim
thanks jim. i finally discards this 'clone' idea, because it's not that easy and seems to produce some buggy problem. so i try to create a xaml resource file, and every time i need to create a instance, i just load the xaml and call the XamlReader.load.
this can bring some performance issue, but i think the cost is acceptable. and i can do styling job in blend for that specified xaml file.

WPF - Creating simple controls to be used on a Canvas

I'm developing a simple WPF UI for image post-processing.
I'd like to create a draggable WPF control to be used on a Canvas which would look roughly like this:
http://img32.imageshack.us/img32/884/photoeditor.png http://img32.imageshack.us/img32/884/photoeditor.png
Both end points ellipses would be draggable and the line joining them would follow as the end points move.
Now, I know how to implement this by simply adding these elements into a Canvas and then implementing the necessary event handling to make the elements move as they're dragged. But that's hard to maintain if I ever want to add other types of draggable controls.
What I'd like to do would be to isolate all the handling into its own class (say DragLine), derived either from FrameworkElement or UIElement. To add this draggable UI element into a Canvas, I'd create an instance of DragLine and just add it to Canvas.Children. The rest of my program would only see DragLine instances and wouldn't need to worry about the lines or ellipses used to draw the new element.
I'd like to implement the line end points using standard shapes such as the Ellipse rather than drawing all of the UI element myself. That's because I'd like to re-use the event handling and hit testing these shapes already implement.
Question: is deriving from FrameworkElement the right way to go about this? The line and end point ellipses would then be just be visual and logical children of in my new class.
If deriving from FrameworkElement is not the recommended way, how would you go about this instead?
If it is, is there a way to simplify its implementation given that the new class would only ever be used on a Canvas (and doesn't need to work well for things like a Grid or a StackPanel)?
Ah, yes, trying to reinvent things that already exist in the framework because you don't know about them. Its been a hobby of mine for quite some time.
What you are doing here is trying to create a special type of adorner. These are relatively easy to do using the bits that already exist in the framework. I suggest you start here.
Another thing you might want to look at are Decorators. Do pretty much the same thing but I think they are more visual. Which one to use depends on your requirements.

Dynamic animations, Commands and separation of concerns

Scenario: I have a (numeric) textbox, a button, and a label. When the button is clicked I'd like the label to "animate" to the numeric value in the textbox (like a spinning dial)
Given:
a) that animations in storyboards cannot have databindings (because they are not FrameworkElements)
b) the lack of triggers in Silverlight
What is the best, and with least coupling of the view model to the view's storyboard, way to update the target animation value and start the animation when the button is clicked?
Note: The scenario is conceptual, so don't concentrate on the specifics of 'animating' numbers or anything
If your goal is strictly to reduce the code-behind in the view I think that an attached behaviour on the Label would work for this. The attached behaviour on the label would expose the number to be animated to and when this number changes an animation (in code) would be run to animate from the old value to the new value.
One drawback is that your animation is now in code, unless you store a templated (just has fake values to start with) version of it in a resource file somewhere where you can load it as needed and replace the templated values.
This article from Josh Smith seems to be the authority on Attached Behaviours;
http://joshsmithonwpf.wordpress.com/2008/08/30/introduction-to-attached-behaviors/
I recently had to solve a similar problem in an MVVM application. My problem was that I needed to animate a container's height from zero to auto. Since Auto is a dynamic value I recognized that the animation (or storyboard) would need to be built (or manipulated) on demand. The solution that I put in place involved using view code-behind to update and fire the animation.
This isn't the most MVVM-friendly approach; however, animations in WPF can be tricky in XAML. Since this solution is really just a workaround for a XAML limitation it seems okay to tie the code directly to the view. Likewise, if the views were mocked then there would be no framework elements to animate, so it really wouldn't make sense to place this code on the VM side.
Does anybody have a better approach?

Resources