WPF development diary-solves the latency of dragging behavior appended to the element, wpf drag

Source: Internet
Author: User

WPF development diary-solves the latency of dragging behavior appended to the element, wpf drag

The premise of this article is to use ItemsControl to dynamically add the most MVVM control to the Canvas.

 

In the previous blog, I used ItemsControls to set Canvs as the layout panel.

Set Canvs. Left and Canvas. Top in ItemContainerStyle.

In MVVM mode.

The next step is to show the drag of the content.

I am sorry to tell you that after two days of exploration, I intend to overturn the above practice.

Although it can be used in this way, I learned something, but the effect is not very good.

 

The reason is that the problem occurs when I need to add a drag function to the Item.

I first did this: I created a custom DragMoveBehavior ),

I first want to test whether Canvas. Left, Canvas. Top are available through behavior settings,

After implementation, I created a new test form, put it into a Canvas, and added a Rectangle to the Rectangle to add my custom drag behavior.

The problem quickly emerged. When I dragged too fast and the rectangular root could not go to my mouse speed, I was dropped and no longer followed me.

Ideally, it should be that I drag faster, the rectangle is smaller, and I should always follow my mouse without time difference.

Although a little slower can follow, I can't bear this operation experience in any way.

I tested it and found that Canvas. SetLeft had a slight latency.

The unconfirmed assumption is that the processing priority of the master thread is inconsistent (DispatcherPriority) when the mouse moves and positions are set ).

At this time, every time the mouse moves a pixel, it requires constant Canvas. SetLeft. Repeated layout operations are undoubtedly not a good choice.

 

Think of the behavior in the Blend with the MouseDragElementBehavior action drag effect, the test found that this function is not defective in operation.

However, I cannot use it directly. Because the relevant location data is to be read and saved, not just a drag effect.

So I will use dotPeek to decompile and see how Microsoft implements it. DotPeek is really powerful, and the biggest feature is that every method generates a very complete Chinese comment. You can even directly view the base class and complete code and Chinese comments.

At the same time, I used Reflector to decompile without comments and reported an error. Only some ILSpy methods have Chinese comments.
Oh, Microsoft used RenderTransform to render deformation! Why did I not think of good things?

However, it is complicated to write by Microsoft. It has more than 600 lines of code and uses matrix deformation to achieve deep cloning of deformation and built-in dependency attributes of X and Y.

Dependency attribute? Can it be used directly? I tried it. No, it didn't change.

It's too sleepy. It's four o'clock in the morning. Go to bed first.

Lying on the bed, ready to go to bed, habitually turn on the mac refreshing vim, suddenly thought, what is the drag effect of the Apple system, tested, found that there are exactly the same problem, however, when the mouse leaves the UI element instantly, the Mouse capture is not lost. Capture? Oh, I understand. If you use MouseCapture to capture elements, it's okay to move the mouse over the UI elements! Rest assured, go to bed.

------------------

Today, the MouseDragElementBehavior class is highlighted, and the source code is adjusted, which is basically available.

The final usage looks like this

<DataTemplate DataType="vm:MyItemViewModel">  <Border Width="120" Height="30" Background="Red">    <i:Interaction.Behaviors>      <ib:MouseDragElementBehavior X="{Binding Left, Mode=TwoWay}" Y="{Binding Top, Mode=TwoWay}" />    </i:Interaction.Behaviors>    <TextBlock HorizontalAlignment="Center" Foreground="White" VerticalAlignment="Center" Text="{Binding Show}" />  </Border></DataTemplate>

However, at this time, I am attaching the drag action to the Border root node in the DataTemplete.

I always feel that something is wrong, where is it? There is slight shaking during the drag, and Border should not be used to drag such a thing. In addition, it does not take advantage of routing events effectively.

At this time, I had doubts about using the ItemsControl Control. I ran to study ListView and read the Demo (address) of the four examples of the official ListView carefully, I found that this is far from what I want. The main purpose of ListView is to display visual items in a custom view. If you want to return to the arms of ItemsControl, for the time being, adjust it based on the combination of ItemsControl + Canvas.

 

Analyze MouseDragElementBehavior carefully and find that the implementation of this class is related to the window complexity!

There is such an implementation of properties that do not feel good:

/// <Summary> /// obtain the root element of the scenario where the associated object is located. /// </Summary> private UIElement RootElement {get {DependencyObject reference = AssociatedObject; for (DependencyObject dependencyObject = reference; dependencyObject! = Null; dependencyObject = VisualTreeHelper. GetParent (reference) {reference = dependencyObject;} return reference as UIElement ;}}

Every time a Move event occurs, that is, every time a pixel is moved, it is necessary to traverse it again to obtain the root element. However, my window is not a Demo with only one node, nesting is still very multi-layer. Although I implemented it in UserControl, it finally found the Windows form element at the outermost layer.

If the window is simple, the drag effect can also be reached in my program, and the drag effect has a certain delay.

There are many similar problems. I decided to rewrite this behavior based on my own ideas to achieve the goal of optimization.

At the same time, I thought, the drag effect is not ideal, drag, will there be a better implementation? Is Border inappropriate? Why don't I use Thumb? After testing, I found that Thumb is very limited. Although it is easy to use, it depends on Canvas for container and does not support direct content. To add content, it is not suitable to cover a layer of decorator.

Continue to optimize the drag behavior according to my original ideas!

First, I deleted the previously written DragMoveBehavior behavior. For details, refer to MouseDragElementBehavior and use RenderTransform to implement a response mechanism for dragging the mouse. In this process, I found the built-in drag behavior class in Blend, and there are many logics and optimizations that I don't need to handle. When I finish the implementation, more than 500 lines of code are changed to more than 100 lines.

After testing, dragging latency in my complicated form reduces a lot.

But I still don't think so! Because there areSlight weight.

Is the behavior I have optimized wrong?

Create a new WPF window. Put it in a rectangle, append the behavior I just wrote, run, and drag the process very smoothly !!!

What is the situation?

The two forms and the same controls have different effects.

The difference is that the former has the following special features:

1. I put the control in UserControl.

2. the form itself is redefined by me, that is, the default form title bar of Windows is removed, and the form template is rewritten.

3. Added Windows Forms for the custom program form. The forms have rounded corners and the forms are transparent.

4. To maximize Custom forms and completely simulate a series of Windows Forms, I used HwndSource to process window messages.

Then start to find the root cause of the problem:

First, only UserControl is not used, and there is still a delay. There is still a delay when only a large amount of content in the form template is deleted. Only comment on the entry for processing window messages, or delay! Dizzy.

The form effect is left. Change the Style of the form. The only difference is that the form is transparent. Change AllowsTransparency to False, Which is smooth!

The reason is found, but why is there such a thing? If it is set to False, the form light emitting, rounded corners, and transparency of the form itself are all affected.

Go through the document. AllowsTransparency is a function that must be set to True when the Background color of the window itself is set to transparent. It can also help to create non-rectangular windows.

In the graphic presentation layer, we can see that non-rectangular windows, also known as Layered windows, are hardware accelerated on operating systems above Vista.

Is hardware acceleration enabled? I use win8.1, and the hardware is also the mainstream configuration. It won't be stuck when playing all the special effects of large 3D online games. Instead, I create a blank WPF form and set it to allow transparency, the background is set to a non-transparent white color. On the top, I put a rectangle and the drag is not smooth. Did you tell me that the hardware is accelerated?

I suddenly felt a deep sense of inferiority when using WPF.

I am unwilling to go to stackoverflow to search for a number of similar problems, but there is no good solution. The basic conclusion is:

1. Most performance problems occur when AllowsTransparency is set to True, especially for animated effects.

2. allowsTransparency is integrated with other technologies. For example, DirectShow cannot run normally, or the WebBrowser content that I encountered earlier cannot be displayed, even classes such as WindowsFromsHost that can allow the use of the Winform control in the WPF form have no function .. That is to say, using it will generate various unexpected bugs, however, you may not be able to think that the transparent settings of this form would be the culprit.

3. Experience shows that hardware acceleration in WPF is not so amazing. At least the problems and complexity it creates are daunting for using its excellent side.

4. For enterprise-level applications, avoid using AllowsTransparency whenever possible. If it's just a simple project, you can play with it.

 

Still sad. For the sake of performance, I decided to remove AllowsTransparency. It is a pity that the form rounded corner and glow are gone. I plan to use another method to achieve the rounded corner and glow, such as double forms.

Finally, since RenderTransform is used, in fact, the Canvas set by ItemsPanel has no practical significance. However, there is no more lightweight layout control to replace. At present, there is no need to use a custom Panel. Canvas is used first.

At the end of the article, I will attach a Demo of the overwrite drag behavior. features:

1. Can be appended to any FrameworkElement.

2. The parent element can be any type of layout control.

3. You can set initial values or bind data for the dependency attribute of X and Y.

4. There is no extended calculation of the drag boundary.

Demo

This article is original. For more information, see the source.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.