How is the size of ManipulationAdorner in Diagram set?

2 Answers 79 Views
Diagram
David
Top achievements
Rank 1
Iron
Iron
David asked on 05 Jan 2023, 07:50 PM | edited on 09 Jan 2023, 10:32 PM

In the process of debugging an issue with the size of Diagram's ManipulationAdorner, I'm wondering how the size is set, please?

This is in WPF, and I'm currently on v. 2021.1.325.40.

In Visual Studio, in the Live Property Explorer, I see the Height and Width listed as being set via "Animation and Visual States" (see attached image), and the values are not what I want.  I'm kind of assuming the properties are being set and held via animation, but I'd be glad for the confirmation.

The issue is that the size of the ManipulationAdorner is incorrect.  The discrepancy happens as the size of the business object represented as selected in the Diagram is changing for business reasons.

In a particular situation, for simplicity, a single NodeViewModelBase is selected.  I see the NodeViewModelBase's Width and Height being set to the correct values as the size of the business object changes.  However, the process of updating the business object has some intermediate, incorrect values for Width/Height in quick succession.  These intermediate values are just as a result of property-change notification order, and one of these intermediate values "sticks" or is the incorrect value that shows.  The correct value is the final value set, however.

Deselecting and reselecting the object results in a correctly sized ManipulationAdorner.

 

I don't have a simple example at hand, unfortunately.  However, is there enough information here to enable any guidance for further debugging, please?  Could the quick and repeated setting of Width & Height be interacting with the timing of WPF's animation system or with the starting/stopping of animations, if these values are indeed being controlled by animation?

I don't think I see any questions of this sort here or elsewhere on other forums.

Thanks for any info and advice!

-David

2 Answers, 1 is accepted

Sort by
0
Dilyan Traykov
Telerik team
answered on 10 Jan 2023, 11:08 AM

Hello David,

Thank you for the provided screenshot.

I'm uncertain as to why the Width and Height properties are placed in the "Animation and Visual States" category of Visual Studio's Live Property Explorer. I am actually unable to select the ManipulationAdorner element via the Live Visual Tree pane at my end.

Nonetheless, I investigated this in our source code and I do not see any animations or triggers that directly affect the size of the ManipulationAdorner. All modifications to the Width and Height properties of the element occur in code and are made in the Resize method which is inherited from DiagramAdornerBase:

        internal void Resize(double width, double height)
        {
            if (!double.IsInfinity(width) && !double.IsInfinity(height))
            {
                if (this.Width != width || this.Height != height)
                {
                    this.Width = width;
                    this.Height = height;
                }
            }
        }

If you wish to further examine this at your end, you can download the source code of the Telerik UI for WPF suite from your Telerik account as explained here: Download Product Files.

I tested the updating of the adorner's properties at my end, however, they seem to be set correctly both when resizing the shape via the mouse and programmatically by updating the bound Width property.

I'm attaching the sample project I used in the process as well as a short recording of the result I observe for your reference. Please note that I've used the Snoop UI inspection tool.

Please let me know if the issue you describe is reproducible in the sample project I've provided and if so, please specify the action steps I need to make to reproduce it. If needed, please modify the project and send it back to me so that I can further investigate.

Regards,
Dilyan Traykov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

David
Top achievements
Rank 1
Iron
Iron
commented on 10 Jan 2023, 06:26 PM

Using Snoop, I still see the size of the ManipulationAdorner being incorrect (in my project).   Snoop doesn't think that the property is under animation control; rather, a locally set value.  That checks out with the code sample you provide.  So perhaps Visual Studio is confused in that matter.

I'll check out your sample project and see if I can get it to misbehave similarly.

Thanks!

Dilyan Traykov
Telerik team
commented on 11 Jan 2023, 12:04 PM

Hello David,

Do let me know if you manage to replicate the same issue you observe with your original project in the sample project I provided.
0
David
Top achievements
Rank 1
Iron
Iron
answered on 25 Jan 2023, 12:22 AM

Here's an example of a project that fails in the same way we see.

After running,

 - select the diagram object
 - hit "Go" and "Back" several times
 - note that the ManipulationAdorner no longer matches the size of object.
 - deselecting and reselecting the object shows a ManipulationAdorner of the correct size.

The changes to the size of the Person object happen in the button handlers and mimic the transient changes that happen with our business object.

I've styled/templated the Diagram, DiagramShape and ManipulationAdorner in ways similar to how we have them done in our application.

 

David
Top achievements
Rank 1
Iron
Iron
commented on 25 Jan 2023, 12:25 AM

and, actually, in the styling, you can comment out or delete the place where we set the Template property of DiagramShape. That's a lot of lines of code, and it doesn't seem to affect the outcome -- I deleted it and still see the same behavior.
Dilyan Traykov
Telerik team
commented on 27 Jan 2023, 05:10 PM

Hello David,

Thank you very much for the provided sample project.

I can confirm that I was able to replicate the behavior you described by going through the action steps you listed.

This appears to be some timing issue when the width of the shape is reset to its initial value.

To overcome this, what I can suggest is to delay the last setting of the Extents property by invoking it via the Dispatcher:

            Dispatcher.BeginInvoke(new Action(() =>
            {
                p.Extents = new Rect3D(x2, ext.Y, ext.Z, w2, ext.SizeY, ext.SizeZ);
            }), System.Windows.Threading.DispatcherPriority.Render);

This correctly resizes the adorner at my end. Can you please give this a try and let me know if such an approach would also work in your original application?

David
Top achievements
Rank 1
Iron
Iron
commented on 30 Jan 2023, 06:10 PM

Hi Dilyan,

Thanks for reply!

I don't think we would introduce any dispatcher threading into the property setting of our core business-logic objects.

To go back to my initial question, and taking into account the logic of the Resize method you posted, can you comment on what's happening in this situation?  Or why are the width & height of the ManipulationAdorner "sticky"?   Alternatively, what is the timing issue to which you refer, please?

 

Dilyan Traykov
Telerik team
commented on 02 Feb 2023, 01:09 PM

Hi David,

I further investigated the specific case in question and it appears that the SizeChanged event of the RadDiagramItem class (from which RadDiagramShape inherits) which is responsible for resizing the manipulation adorner is not fired with this sequence of setters. Please note that this event is native and comes from the FrameworkElement class which the diagram items inherit.

This leads me to believe this is behavior stems from the WPF framework and is due to some optimization when setting the Extents property in close succession. You can notice that commenting out the first or second line in the following code snippet also resolves the issue:

            p.Extents = new Rect3D(x3, ext.Y, ext.Z, w3, ext.SizeY, ext.SizeZ);
            p.Extents = new Rect3D(x2, ext.Y, ext.Z, w3, ext.SizeY, ext.SizeZ);
            p.Extents = new Rect3D(x2, ext.Y, ext.Z, w2, ext.SizeY, ext.SizeZ);

This, combined with the fact that using the BeginInvoke method correctly resolves the size of the adorner leads me to believe this is some timing issue caused by the framework.

With this said, if using the Dispatcher in your business objects will not be possible, would you find it possible to batch the update operations so that the properties are not set in such a quick succession? You can use a timer and a private field and only set the bound property only after some interval elapses - every second, for example.

Please let me know if such an approach would be applicable for you.

David
Top achievements
Rank 1
commented on 10 Feb 2023, 11:37 PM

Hi Dilyan,

Thanks for the information and analysis!

There's nothing special about three updates in quick succession, in our use case.  I just found it to be the minimum necessary to demonstrate the behavior in the sample.  Sometimes we see four, sometimes we see six -- the point being that they are reflections of transitory, temporary changes in the business objects (which are set up with property-change notifications and so correctly report their property changes).

To say a bit more about using a Dispatcher in the business objects or batching the property-change notification...  it's not the case that it's not possible but rather that I think it would be poor design to have these UI considerations pushed that far back into our tech stack. That, however, suggests that the dispatching could reasonably live within a viewmodel, and that turned out to be a reasonable solution.

There aren't a lot of comments/questions online about FrameworkElement.SizeChanged not firing.  However, one line here:
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.frameworkelement.sizechanged
"The layout engine has internal logic that stabilizes the values before an object fires the event again... "
is suggestive of what's going on.  Now, admittedly, that's for UWP, but it's plausible that the same mechanisms are in place in earlier versions.

So, while I don't love using a dispatcher as a work-around, it does generate the right ManipulationAdorner visuals for us now. 

I could also recommend that Telerik investigate more reliable mechanisms than SizeChanged to have the ManipulationAdorner respond to size changes in diagram objects.

Thanks!

-David

Dilyan Traykov
Telerik team
commented on 13 Feb 2023, 09:29 AM

Hello David,

Thank you very much for this valuable feedback.

I can agree that an alternative mechanism can be used in order to improve the behavior of the adorner in such scenarios, however, we would need to invest some time to research possible approaches and determine their complexity. For the purpose, we would need to prioritize and plan this process.

With this said, you can log a new item in our feedback portal and if it accumulates enough demand, we will consider such an improvement for one of our future releases.

In the meantime, I do hope you find the current solution of using the Dispatcher satisfactory for the time being. Do let me know if I can further assist you with anything else.

Tags
Diagram
Asked by
David
Top achievements
Rank 1
Iron
Iron
Answers by
Dilyan Traykov
Telerik team
David
Top achievements
Rank 1
Iron
Iron
Share this question
or