none
Cached properties and ThisDocument_BeforeSave handler RRS feed

  • Question

  • Hello,

    Consider the following example: (VS2008, Office 2007)

    public partial class ThisDocument
    {
        [Cached]
        public int nIntValue = 0;
    
        private void ThisDocument_Startup(object sender, System.EventArgs e)
        {
          MessageBox.Show(nIntValue.ToString());
        }
    
        private void ThisDocument_Shutdown(object sender, System.EventArgs e)
        {
        }
    
        //VSTO generated code omitted
    
        private void ThisDocument_BeforeSave(object sender, Microsoft.Office.Tools.Word.SaveEventArgs e)
        {
          nIntValue = 1;
        }
    }
    

     

    1st time you open the document the message box  displays 0 as expected.

    However, after you save the document and open it again, it still displays 0 instead of 1 that was intended.

    This indicates, that all the cached data fields, are saved before ThisDocument_BeforeSave() is executed and that all changes in those values that might take place inside the handler are ignored.

    I have also verified this behavior by using breakpoints, in a cached field with a custom serializer, where the breakpoint in the serializer is first hit, after which the breakpoint in the ThisDocument_BeforeSave() follows.

    My question is: Shouldn't this be considered a BUG in the cached fields saving mechanism? If the framework exposes a handler which is supposed to trigger BEFORE all saving operations, one expects this to be true for ALL data streams. Semantically, the code inside the "BeforeSave" handler has a chance to alter the document data (regardless of data stream) and still have them safely saved.

    Is there a workaround for this?

    Thanks,

    Jason

     

    Thursday, August 18, 2011 10:06 AM

Answers

  • No, that's not it: Try it also like this:

    Save the document by Ctrl+S, or clicking the Save button. Then try to close the document. But when it asks you "do you want to save the document?" (even if you just saved it!), choose "No". We only want the event to be triggered once, right?

    Then open the document again. Still 0 right?

    So, the event got fired. but the variable didn't get saved!

    That's the problem!

    Microsoft has coded the event to be triggered like this:

    [internal code that saves cached properties]
    ThisDocument_BeforeSave()
    [internal code that saves main document data except cached properties]

    while it should be triggered like this:

    ThisDocument_BeforeSave()
    [internal code that saves cached properties]
    [internal code that saves main document data except cached properties]

    See what I mean?

     


    Jason Orphanidis
    Thursday, August 25, 2011 7:10 AM

All replies

  • Hi Jason

    It's been a while since I've worked with cached data, but as I recall you do need to first initialize the cache. And I don't think you should be assigning a value to the variable to be cached at the class level - that would certainly override the cached value when the solution is started each time. See for example this topic in the MSDN documentation

    http://msdn.microsoft.com/en-us/library/48b7eyf3.aspx


    Cindy Meister, VSTO/Word MVP
    Thursday, August 18, 2011 12:42 PM
    Moderator
  • Hi Cindy, thanks for your reply.

    The attribute [Cached] is all it is needed for caching to initialize. StartCaching and StopCaching methods are used as an alternative to the [cached] attribute.

    Initialization at class level takes place before loading the cached values. So when inside ThisDocument_Startup(), the cached value (if it exists) prevails. However, I removed the initialization and changed ThisDocument_Startup() as follows, but the results are the same...

    private void ThisDocument_Startup(object sender, System.EventArgs e)
    
    {
    
      if (nIntValue != 1) 
    
       nIntValue = 0;
    
    
    
      MessageBox.Show(nIntValue.ToString());
    
    }
    
    

     


    Thursday, August 18, 2011 1:15 PM

  • Clarification for reproducing the bug:

    Close the document by hitting Ctrl+F4 and when asked if you want to save the document, choose yes. Then, open the document again (easiest way is to go to the recently opened documents list and get it from there).

    If you first save the document (by Ctrl+S for example) and then close it, the prompt for saving the document will still appear (this is also a bug: why ask again for saving since you already saved it?*). If you choose yes, the document will be saved for a 2nd time. This time the value of the cached property will get saved correctly, but only because its value had been changed from the 1st save, not from the 2nd. To see this, choose 'no' at the prompt and open the document again: the message box will display the value of '0'.

    ------------------------------------------
    *The answer is of course that ThisDocument_BeforeSave() has been executed from the 1st save, changing the value of the cached property, thus making the whole document dirty


    Jason Orphanidis
    Friday, August 19, 2011 6:12 AM
  • Hellow again,

    Can someone try to reproduce the error in VS2010 & Office 2010? Reporting bugs for VS2008/Office 2007 is currently closed. If the bug is still there even in the latest versions, I can open a message there.

    Thanks,

    Jason


    Jason Orphanidis
    Tuesday, August 23, 2011 8:38 AM
  • Hi Jason,

     

    Thanks for posting in the MSDN Forum.

     

    As far as I know, the variable’s types must be public and meet the requirements of XmlSerializer which marked by Cached attribute.

     

    I would recommend try it via a DataSet object.

     

    I hope what I said can help you.

     

    Have a good day,

     

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, August 24, 2011 10:55 AM
    Moderator
  • Hi Tom,

    As you can see in the code above, the variable's type is the simplest of all (int, so meets the requirements of XmlSerializer) and already marked as public.

    It has nothing to do with the data type used (as long as it supports XML serialization), but with the sequence of the triggering of the event ThisDocument_BeforeSave, being called AFTER cached variables are saved, instead of BEFORE.

    Try out the example yourself, it's just 4 lines of code!

    If the problem still exists in VS2010/Office 2010 I can open a support message in Microsoft and report the bug.

    Thanks


    Jason Orphanidis
    Wednesday, August 24, 2011 11:35 AM
  • Hi Jason,

     

    I found I can get the correct value under Visual Studio 2010, Word 2010. And it seems that integer variable also can be cached. I tried your snippet on my side. I get “1” when I reopen my test document.

     

    Have a good day,

     

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, August 25, 2011 3:20 AM
    Moderator
  • Hi Tom,

    Thanks for taking the time to recreate the case on your side. Did you make sure to only save the document *once*, by closing it as I described?

    "Close the document by hitting Ctrl+F4 and when asked if you want to save the document, choose yes. Then, open the document again (easiest way is to go to the recently opened documents list and get it from there)"

    Thanks!


    Jason Orphanidis
    Thursday, August 25, 2011 6:17 AM
  • Hi Jason,

     

    No, it you hit Ctrl+F4 the cached variable is “0”. I found it will be “1” if you click save button at the left top of the window before you hit Ctrl+F4. It seems that Ctrl+F4 will not fire the event.

     

    Have a good day,

     

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, August 25, 2011 6:53 AM
    Moderator
  • No, that's not it: Try it also like this:

    Save the document by Ctrl+S, or clicking the Save button. Then try to close the document. But when it asks you "do you want to save the document?" (even if you just saved it!), choose "No". We only want the event to be triggered once, right?

    Then open the document again. Still 0 right?

    So, the event got fired. but the variable didn't get saved!

    That's the problem!

    Microsoft has coded the event to be triggered like this:

    [internal code that saves cached properties]
    ThisDocument_BeforeSave()
    [internal code that saves main document data except cached properties]

    while it should be triggered like this:

    ThisDocument_BeforeSave()
    [internal code that saves cached properties]
    [internal code that saves main document data except cached properties]

    See what I mean?

     


    Jason Orphanidis
    Thursday, August 25, 2011 7:10 AM
  • Hi Json,

     

    I tracked the process, I found ThisDocument_BeforeSave will be fire at the click “save” button and close Word. I assume that the cached variables will save the changed value when the document will be close. And ThisDocument_BeforeSave will not affected the cached variables’ save. Only select “Save” when closing Word will save the changing of the variable.

     

    Have a good day,

     

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, August 25, 2011 8:28 AM
    Moderator
  • OK, so I suppose you confirm that it is a bug.

    I will report it in Microsoft and let them know.

    Thanks you your help.


    Jason Orphanidis
    Thursday, August 25, 2011 9:43 AM