The premise of this article is to combine the most mvvm of ItemsControl to dynamically add controls in the canvas
The previous blog talked about me by using the Itemscontrols internal settings Canvs as the layout panel
and set canvs.left in Itemcontainerstyle, Canvas.Top.
To implement the ability to set a custom location to display individual content in the MVVM mode.
The next step is to show the drag of the content.
I am sorry to tell you that after these two days of exploration, I intend to overturn the above practice.
Although this can be used to learn something, but the effect is not very good.
The reason for this is that when I need to add a draggable feature to the Item later, the problem occurs.
I did this at first: I created a custom draggable behavior class (Dragmovebehavior),
I was going to test first by setting Canvas.Left by behavior, whether Canvas.Top is available,
When I realized it, I created a new test form, put it in a canvas, stuffed it with a rectangle (Rectangle), and added my custom drag behavior to the rectangle.
The problem soon appeared, when I dragged too fast, the rectangle root not on my mouse speed, was left behind, no longer follow me away.
The ideal state, should be I drag the faster, the rectangle is small, also should have no time difference has been following my mouse to go to AH.
Although it's a little bit slower to follow, I can't stand the experience anyway.
I tested it to see if there was a slight delay in the canvas.setleft.
The guesswork is that the mouse moves and sets the position of two tasks, the processing priority of the primary thread is inconsistent (dispatcherpriority).
This time, the mouse to move a pixel point, all need constant canvas.setleft, repetitive layout operation is undoubtedly not a good choice.
The thought that the behavior in Blend has a mousedragelementbehavior behavior drag effect, the test found that the function is not defective in operation.
However, I am not able to use them directly. Because the relevant location data is to be read and saved, not just a drag effect.
So I just use DotPeek anti-compilation to see how Microsoft is implemented. DotPeek is strong, and the biggest feature is that each method produces a very complete Chinese annotation. You can even view the base class directly, as well as complete code and Chinese comments.
And I also use Reflector anti-compilation without comment also reported error. Ilspy only some of the methods have Chinese comments.
Oh, it turned out that Microsoft was using RenderTransform to render the deformation! Good thing, how did I not think of it?
However, Microsoft wrote more complex, more than 600 lines of code, with the matrix deformation, the realization of the deformation of deep cloning, built-in X, y dependency properties and so on.
dependency property? Can it be used directly? Try it, no, no change.
Too sleepy, four o'clock in the morning, sleep first.
Lying on the bed, ready to sleep, accustomed to turn on the Mac Shuangshuang vim, suddenly thought, the apple system drag effect is how, test the next, found unexpectedly have exactly the same problem, however, in the moment the mouse out of UI elements, and did not lose the mouse capture. Capture? Oh, I understand, if you use MouseCapture to capture the elements, the mouse is not on the UI element is not a problem! Rest assured, sleep.
——————————————————
Today focus on the Mousedragelementbehavior class to understand, and the source code adjustment, the basic available.
The ultimate way to use it looks like this
<DataTemplateDataType= "Vm:myitemviewmodel"> <BorderWidth= "+"Height= "+"Background= "Red"> <i:interaction. Behaviors> <Ib:mousedragelementbehaviorX="{Binding left, mode=twoway}"Y="{Binding Top, mode=twoway}" /> </i:interaction. Behaviors> <TextBlockHorizontalAlignment= "Center"Foreground= "White"VerticalAlignment= "Center"Text="{Binding Show}" /> </Border></DataTemplate>
However, this time, I was in datatemplete in the border root node attached to the drag behavior.
Always feel what is wrong, what is wrong, drag when there are subtle shaking, and border should not be used to dry drag such things, there is no effective use of the advantages of routed events.
At this time I am using ItemsControl this control generated doubts, ran to study the next ListView, looked at the official ListView Four examples of the demo (address) carefully read the specific use of the demo, found that this and I want things very far, The main purpose of the ListView is to be able to display the visual items in a custom view, or to go back to the bosom of ItemsControl, for the time being, let's adjust it with the combination of ItemsControl + Canvas.
Careful analysis of the mousedragelementbehavior, and finally found that the official implementation of this class is related to the complexity of Windows!
There is an implementation of a property that feels bad:
/// <summary>///gets the root element of the scene where the associated object resides. /// </summary>PrivateUIElement rootelement{Get{DependencyObject Reference=Associatedobject; for(DependencyObject DependencyObject =reference; DependencyObject!=NULL; DependencyObject=visualtreehelper.getparent (Reference)) {Reference=DependencyObject; }returnReference asUIElement; }}
Each time a move event is generated, that is, each pixel is moved, it is re-traversed to get a root element. However, my window is not a demo with a node, nested or a lot of layers, although I was implemented in UserControl, but eventually it found the outermost Windows Forms elements.
If the window is simple, then the drag effect can also, into my program, the drag effect has a certain delay.
A lot of similar questions, I decided to rewrite this behavior according to my own thinking, in order to achieve the goal of optimization.
At the same time, I think, the drag effect is not ideal, drag, will there be a better implementation of it? Border not very suitable? Then why don't I use thumb? Tested, found very limited, although the thumb is simple to use, but rely on the canvas to do the container, and do not support the direct content, I want to add content, can only think of covering a layer of adorners, not very suitable.
Let's continue to optimize the drag behavior as I originally thought!
First of all, I deleted the previous written dragmovebehavior behavior of the content, referring to Mousedragelementbehavior, with the RenderTransform to implement the mouse drag response mechanism. This process I found in Blend's built-in drag behavior class, there's a lot of logic I don't need to deal with and places to optimize. When I finished writing the required implementations, more than 500 lines of code became more than 100 lines.
Tested, drag latency in my complex form has been reduced a lot.
But I still think it's wrong! Because of the slightly heavier feeling when dragging.
Did I optimize the behavior to achieve the wrong?
Creates a new WPF window. Put in a rectangle, attach the behavior I just wrote, run, drag the process very smooth!!!
What's the situation?
Two forms, the same control, use the effect is very different, think of the reason.
The special difference between the former is:
1. I put the controls inside the UserControl.
2. The form itself is redefined by me, that is, the Windows system default form title bar is removed and the form template is rewritten.
3. Custom Programs form added Windows Forms Glow, form fillet, form transparent
4. To maximize the custom form and to fully simulate a series of effects on Windows system forms, I used HwndSource to process the window messages.
So start looking at the root cause of the problem:
First, no UserControl, no changes, or delays. Only a large amount of content in the form template is deleted, and there is still a delay. Note only the processing entry for the window message, or the delay! Dizzy.
The rest of the form effect, change the style of the form bar, the only relationship is the remaining form transparent, allowstransparency changed to False, smooth!
The reason is found, but why is there such a thing? God, set to False, the glow and fillet of the form and the transparency of the form itself are affected.
To go through the document, AllowsTransparency is a way to allow the window itself to set Background as transparent color, it must be set to True before it will work, and can help implement non-rectangular window creation.
In the graphic rendering layer article, you can see that the non-rectangular window is also called layered windows, on the vista above the operating system is hardware-accelerated.
Does this mean that hardware acceleration is turned on? I use the win8.1, hardware is also the mainstream configuration, play large 3D online games effects full Open will not card, and I re-build a WPF blank form, set to allow transparent, the background is set to non-transparent white, on this I put a rectangle even drag is not smooth, you tell me this also hardware acceleration?
I suddenly had a deep inferiority complex with WPF.
Not reconciled, ran to StackOverflow on the search, similar problems are quite a lot, but there is no good solution. The basic conclusions are:
1. Most performance problems occur because AllowsTransparency is set to true, especially the animation class effect.
2. AllowsTransparency and other technology integration, such as DirectShow does not work properly, such as my previous encounter WebBrowser content can not display, and even windowsfromshost This class that allows you to use the WinForm control in a WPF form has lost its role ... In other words, using it will produce unexpected bugs, and you may not be able to think of the form's transparent setting as the culprit.
3. Experience has shown that hardware acceleration in WPF is not surprisingly effective, at least because of the problems and complexities that it creates that are intimidating to the good side of using it.
4. If you are an enterprise application, try to avoid using allowstransparency. If it's just a simple project then you can play.
is still sad. For performance, I decided to remove the allowstransparency, the form fillet and glow No, unfortunately, I intend to have time in the back for a way to achieve fillet and glow, such as a double form.
Finally, since the use of rendertransform, the fact that the canvas set by Itemspanel has no practical significance. However, there is no substitute for a lighter layout control, and it is not necessary to use a custom Panel,canvas first.
At the end of the final, attach my rewritten drag behavior to the Demo, features:
1. Can be attached to any frameworkelement element.
2. The parent element can be any type of layout control.
3. x, Y is a dependency property that can set initial values or participate in data binding.
4. There are no calculations to extend the draggable boundary.
Demo
This article original, reproduced please indicate the source.
WPF Development Journal-Resolving delay of drag behavior attached to elements