Visio CellChanged and FormulaChanged Events firing when they shouldn't.

Started by bwharrington, April 22, 2019, 09:34:59 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

bwharrington

Hi all,

I've been agonizing over my understanding of Visio events for quite some time now. I'm attempting to control these events by unhooking them and using event suppress code by I am still seeing calls to these events when their should not be.

I'm currently using a Cell Changed event which I hook up to the Application Object on Startup. In a perfect world, this event only ever fires when a user changes a cell, not a programmatic operation.

I am trying to control this with a couple methods in the ThisAddin.cs file,

public void TurnOnCellChanged()
{
    Application.CellChanged += Application_CellChanged;
}

public void TurnOffCellChanged()
{
    Application.CellChanged -= Application_CellChanged;
}


A call will be made prior to an automated event to TurnOffCellChanged like this,

Globals.ThisAddIn.TurnOffCellChanged();

I am also using an event suppressor a colleague of mine created prior to his departure. Although he admits he still had the same challenges I have now with the events firing unexpectedly.

using (var events = new VisioEventSilencer(application))
{
.... Do work
}

I have attached the implementation of the VisioEventSilencer in the text file. We got this code from the internet.

With all of this, I am still seeing calls to CellChanged through the debugger and using the Visio Event Monitor. This causes performance issues when we need to created many shapes having upwards of 50-100 properties a shape (In the worse case).

What more of a head-scratcher, since I have used the Event Monitor, I see calls to FormulaChanged but I have never hooked up a FormulaChanged Event.

I've suspected all along that there is something I do not understand about the events. Even more so after seeing calls to an event that I have never hooked up.

Can anyone explain what may be going on or try to bridge my gap of understanding? Maybe something I am missing entirely?

Thanks,



Nikolay

The CellChanged event is fired when (any) cell value is changed, like it's name says. Changed either directly by user, or indirectly by Visio engine because of something (shape change). I think it might be a bad idea to subscribe to that on application level, you'll get tons of those events.

If you want to track user modifying shape data, you could use FormulaChanged instead,
this should fire when user edits shape data, but not when shapes are moved, resized or connected to each other.

As for the performance. If you want performance in Visio, do not use C#, go with VBA instead. Preferably with Visio 2010. It'll be times faster.

If you cannot do that, you could check this C# visio performance tips article:
https://blogs.msdn.microsoft.com/mailant/2004/09/22/dev-luv-visio-development-top-five-performance-tips/

In particular, if you have 50 properties, set them all at once using SetFormulas(), and if you drop 100 shapes, drop them all at one using DropMany()

About your EventSilencer - from what I see, the code does not seem to completely block "CellChanged" events from being fired,
instead it "batches" them using DeferRecalc (so the events will probably fire when exiting the silencer's scope)

Also, as far as I remember, += / -= do not really turn off the event firing in Visio, these simply disable the event handler in your C# code.
If you really want to turn off the event firing in Visio, you could try AddAdvise approach instead.

As for the EventMonitor, the "CellChanged" event may be simply filtered out. Means, you can tell that thing which events to capture (it has options)

bwharrington

Thanks for the detailed reply Nikolay,

If you want to track user modifying shape data, you could use FormulaChanged instead,
this should fire when user edits shape data, but not when shapes are moved, resized or connected to each other.

I'll do some additional investigation on this. My initial tests did not seem to reduce the number of calls. But I now I understand where I may make some gains.

As for the performance. If you want performance in Visio, do not use C#, go with VBA instead. Preferably with Visio 2010. It'll be times faster.

Unfortunately this is not an option but its worth considering for future projects. Is there any information that your aware of that outlines this?

If you cannot do that, you could check this C# visio performance tips article:
https://blogs.msdn.microsoft.com/mailant/2004/09/22/dev-luv-visio-development-top-five-performance-tips/

Definitely following most of these. Currently implementing dropmanyu. Its working its way through our workflow and SetFormulas() is next on my list.

About your EventSilencer - from what I see, the code does not seem to completely block "CellChanged" events from being fired,
instead it "batches" them using DeferRecalc (so the events will probably fire when exiting the silencer's scope)

This completely explains some of the things I am seeing.

Also, as far as I remember, += / -= do not really turn off the event firing in Visio, these simply disable the event handler in your C# code.
If you really want to turn off the event firing in Visio, you could try AddAdvise approach instead.

I will do some digging on AddAdvise.

Thank Nikolay, there is quite a but here I had no grasped.