The EntitySpaces Community

Share and learn about the EntitySpaces Architecture.
Welcome to The EntitySpaces Community Sign in | Join | Help
in
Home Forums Photos

DGV only updates values when I mouse over the cell

Last post 09-09-2008, 9:25 PM by sklett. 10 replies.
Sort Posts: Previous Next
  •  03-15-2008, 3:26 PM 8414

    DGV only updates values when I mouse over the cell

    I've got a problem with my DGV that is bound to an entity collection.  My application is a client / server setup so when the server notifies my clients that a cached item has been modified the client will load the modified entity and sync the cached entity in the collection with the "fresh" data.

    This works fine except I need to mouse over the cells (or scroll, resize... trigger a paint basically) to see the updated data.

    Is there a method on the esEntity I can call that will send the property change to the DGV for the modified properties?  I'm sure it's already doing this as my entity support INotifyPropertyChanged, but the DGV isn't take the notification seriously (enough) to do anything about it.

    Anyone else experienced this?

     

  •  03-15-2008, 4:53 PM 8415 in reply to 8414

    Re: DGV only updates values when I mouse over the cell

    As long as "Support INotifyPropertyChanged" is checked when you generate, then the DataGridView should immediately reflect a change in the bound collection. We have a TestForms app to manually test this.

    It works the old way, with casting:

    Employees entity = (Employees)collection[0];
    entity.LastName = "Notified";

    The new way, without having to cast:

    collection[0].LastName = "Notified";

    With FindByPrimaryKey():

    Employees entity = collection.FindByPrimaryKey(1);
    entity.LastName = "Notified";

    And, with Detach, change, Attach:

    Employees entity = collection.DetachEntity(collection[0]);
    entity.LastName = "Notified";
    collection.AttachEntity(entity);

    In all cases, both with, and without, using a BindingSource between the DGV and the collection, the field is updated immediately.

    Is the caching mechanism somehow intercepting the change notification, and not passing it on? Does the collection have any virtual columns or extended properties that do not implement INotifyPropertyChanged? Have you tried a BindingSource.ResetBindings(false) and/or a DataGridView.Refresh() after the cache finishes updating?


    David Neal Parsons
    www.entityspaces.net
  •  03-16-2008, 9:50 AM 8425 in reply to 8415

    Re: DGV only updates values when I mouse over the cell

    Hi David,

    The caching (the word cache is a stretch, it's just a collection I maintain in a singleton) doesn't do anything that should interfere.

    Here is the code that does the update:

     

    Code:
    1    private void UpdateCachedDocument(FaxMessage document, int documentID)
    2    {
    3        FaxMessage freshCopy = new FaxMessage();
    4        freshCopy.Query.Select(BuildDocumentQueryWithoutAttachment())
    5        .Where(freshCopy.Query.DocumentID == documentID);
    6        freshCopy.Query.Load();
    7    
    8        if (freshCopy.ProcessedByID.HasValue)
    9        {
    10           document.ProcessingUser =
    11               _userAccountService.GetUserAccountFromUserID(freshCopy.ProcessedByID.Value);
    12       }
    13   
    14       document.DocProcState = freshCopy.DocProcState;
    15       document.DocProcStatusID = freshCopy.DocProcStatusID;
    16       document.DocTypeID = freshCopy.DocTypeID;
    17       document.FileTypeTypeID = freshCopy.FileTypeTypeID;
    18       document.From = freshCopy.From;
    19       document.ProcessedByID = freshCopy.ProcessedByID;
    20       document.Subject = freshCopy.Subject;
    21       document.To = freshCopy.To;
    22   
    23       //  AcceptChanges() will prevent the entity from being
    24       //  saved should the collection be saved
    25       document.AcceptChanges();
    26   }
    


     I tried commenting out the last line and it made no difference.

    This is a head scratcher.  I thought there was a chance it was a threading issue as my server invoked events are handled on a separate thread, but because the DGV (UI Thread) is bound to the collection, I've executing the above method in the UI context so this shouldn't be an issue. 

     

    Code:
    1    /// <summary>
    2    /// This is the handler for server notifications.  These events come in
    3    /// on a background thread, so we need to make any UI or UI-Bound data
    4    /// changes on the UI thread.
    5    /// </summary>
    6    /// <param name="data"></param>
    7    public void OnDocumentStatusChanged2(DocumentsUpdatedEventArgs data)
    8    {
    9        try
    10       {
    11           //  We don't handle our own events back from the server
    12           if(data.ClientID == this.ClientID)
    13           {
    14               return;
    15           }
    16   
    17           //  We need to handle the updates on the UI thread because there
    18           //  are controls bound to the Document collection.
    19           _uiContext.Post(delegate { HandleDocumentUpdate(data); }, null);
    20       }
    21       catch (Exception e)
    22       {
    23           Console.WriteLine(e.ToString());
    24       }
    25   }
    

     

    The above code then calls the Handler:

     

    Code:
    1    /// <summary>
    2    /// Handles the updates to the cached FaxMessage items
    3    /// </summary>
    4    /// <param name="changeType"></param>
    5    /// <param name="faxIDs"></param>
    6    public void HandleDocumentUpdate(DocumentsUpdatedEventArgs data)
    7    {
    8        try
    9        {
    10           foreach (DocumentUpdatedInfo info in data.UpdatedDocuments)
    11           {
    12               FaxMessage document = GetDocumentFromCacheThrowIfMissing(info.DocumentID);
    13   
    14               if (true || info.DataModified)
    15               {
    16                   UpdateCachedDocument(document, document.DocumentID.Value);
    17               }
    18   
    19               //  Raise the events
    20               if (DocumentUpdated != null)
    21               {
    22                   DocumentUpdated(this, new InboundDocumentUpdatedEventArgs(document, document.ProcessingUser, info.UpdateType));
    23               }
    24           }
    25       }
    26       catch(Exception eeeee)
    27       {
    28   
    29       }
    30   }
    31   
    32   private FaxMessage GetDocumentFromCacheThrowIfMissing(int documentID)
    33   {
    34       FaxMessage document = _documents.FindByPrimaryKey(documentID);
    35       Guard.ReferenceNotNull(document, string.Format("Failed finding document {0} in the cache", documentID));
    36   
    37       return document;
    38   }
    
     

    If you can think of anything else I could try let me know.  I'm going to try working with the collection directly and see if that makes a difference.

  •  03-16-2008, 11:04 AM 8427 in reply to 8425

    Re: DGV only updates values when I mouse over the cell

    I'm hot-on-the-trail.... pretty sure I know what it is.

    The columns that aren't updating are extended properties that depend on the values of other properties.  For example, 2 properties:

    1. DocProcStatusID  - plain' ol DB backed property
    2. DocProcStatusTitle - Extended property, return value depends on the vale of DocProcStatusID

    So, my "cache updating" isn't updating my extended properties and as such the change notification isn't being passed for them.

    What I suspect I need to do is override DocProcStatusID and send a notification for any dependent properties in the setter. 

    The question now is:  How to I raise a change notification event for an extended property?

  •  03-18-2008, 4:16 PM 8458 in reply to 8427

    Re: DGV only updates values when I mouse over the cell

    Anyone? Suggestions? Tips? Please....?
  •  04-07-2008, 1:11 AM 8740 in reply to 8458

    Re: DGV only updates values when I mouse over the cell

    Hmmm...

    I thought for sure this would work, but it doesn't.  I still need to hover over the cell to get a refresh.

     

    Code:
    1    public override short? DocProcStatusID
    2    {
    3        get
    4        {
    5            return base.DocProcStatusID;
    6        }
    7        set
    8        {
    9            base.DocProcStatusID = value;
    10           OnPropertyChanged("StatusTitle");
    11       }
    12   }
    13   
    14   public string StatusTitle
    15   {
    16       get
    17       {
    18           InboundDocumentStatusEnum status = (InboundDocumentStatusEnum)this.DocProcStatusID.Value;
    19   
    20           if( ( status == InboundDocumentStatusEnum.InProcess || 
    21                 status == InboundDocumentStatusEnum.Processed || 
    22                 status == InboundDocumentStatusEnum.Started ) &&
    23                 ProcessingUser == null)
    24           {
    25               int error = 1;
    26           }
    27   
    28           switch(status)
    29           {
    30               case InboundDocumentStatusEnum.New:
    31                   {
    32                       return "Process";
    33                   }
    34               case InboundDocumentStatusEnum.Started:
    35                   {
    36                       return "Started";
    37                   }
    38               case InboundDocumentStatusEnum.InProcess:
    39                   {
    40                       //ThrowIfUserAccountRefNull();
    41                       if (ProcessingUser != null)
    42                       {
    43                           return string.Format("In Process..., ({0})", ProcessingUser.FullName);
    44                       }
    45                       else
    46                       {
    47                           return "In Process...";
    48                       }
    49                   }
    50               case InboundDocumentStatusEnum.Processed:
    51                   {
    52                       //ThrowIfUserAccountRefNull();
    53                       if (ProcessingUser != null)
    54                       {
    55                           return string.Format("Processed, ({0})", ProcessingUser.FullName);
    56                       }
    57                       else
    58                       {
    59                           return "Processed";
    60                       }
    61                   }
    62               default:
    63                   {
    64                       throw new Exception(string.Format("Unsupported InboundDocumentStatusEnum value: {0}", status));
    65                   }
    66           }
    67       }
    68   }
    
    Can anyone think of anything else I should try?  Can someone from ES confirm that OnPropertyChanged with an extended property is valid and should work?
     
  •  04-07-2008, 5:59 AM 8744 in reply to 8740

    Re: DGV only updates values when I mouse over the cell

    I'm traveling right now, it will require me creating a sample app to test this, if you can table it for 10 days I can get the answer, I'm sorry but in Florida on vacation right now.
    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  04-07-2008, 4:24 PM 8767 in reply to 8744

    Re: DGV only updates values when I mouse over the cell

    Tabled, but with Outlook reminder to poke you in 10 days.
  •  08-13-2008, 7:43 AM 10722 in reply to 8767

    Re: DGV only updates values when I mouse over the cell

    Hi Mike,

    Do you think we can revive this issue?  It's still a problem for me.
     

  •  08-13-2008, 2:31 PM 10736 in reply to 10722

    Re: DGV only updates values when I mouse over the cell

    Have you tried a bindingSource1.ResetBindings(false) or a dataGridView1.Refresh() after the cache finishes updating? In my tests, either one of those will immediately display the new value of a read-only, calculated extended property, after a dependent property has been changed.


    David Neal Parsons
    www.entityspaces.net
  •  09-09-2008, 9:25 PM 11262 in reply to 10722

    Re: DGV only updates values when I mouse over the cell

    sklett:

    Hi Mike,

    Do you think we can revive this issue?  It's still a problem for me.
     

     Ah HAH!  I think I have finally found what the problem is (hopefully).  It all started when when updating a property on an entity wasn't updating the row in the DGV representing the entity.  The data was changing but the DGV wouldn't repaint unless I moused over.  To make things tricker the property in question was a custom property.

    My initial solution was to call OnPropertyChanged passing the id of the custom property.  This seems like it should work for-sure... but... it didn't.  I just found out why: While stepping into OnPropertyChanged I noticed that PropertyChanged handler was null.

    It never actually gets called.  I've been off Win32, .Net, DGV, ES, etc programming for quite a few months and am rusty.  Maybe someone can straighten me out on this: If I have an object bound (through a collection) to a DGV shouldn't the bound properties have a subscriber for PropertyChanged?  There seems to be just the one PropertyChanged instance for each entity and I don't understand how/why it's null if I have it bound to a DGV.

    Any clarification/guidance much appreciated.
     

View as RSS news feed in XML