Ticket Q564493
Visible to All Users

Refresh DetailView of NonPersistent object using Timer in WinForms

created 11 years ago

I would like to update a field on a DetailView for a non-persistent object (inherited from XPCustomObject) using the Timer.Elapsed event in a WinForms XAF Application. While the timer runs in the background (started in the ViewController<DetailView>.OnActivated method) the user should be free to edit any other fields on the form, which includes lookup editors, date editors and strings. The values I want to update have the [ImmediatePostData] attribute in the Business Object class, and use the standard XAF SetPropertyValue<> setters.
In the Controller's Timer Elapsed method I've tried various combination of View.Refresh, View.ObjectSpace.Refresh, View.UpdateItem etc without being able to get the new values to display. I've tried setting the values indirectly using a custom SetFieldValue method on the object which explicitly includes a Changed(property) call - but still no update until the user clicks on the field, when the value set in the background is suddenly displayed.

ObjectSpace refreshes do impact on the user's ability to use persistent object lookup editors (ObjectEdit/LookupEdit) - they go blank when the ObjectSpace is refreshed, which I need to avoid if the user is to be able to use the DetailView uninterrupted in the foreground.
What is the magic process to use to refresh the displayed values of a Non-Persistent object's DetailView ViewItems from a Timer.Elapsed event (or presumably any other operation running in a different thread), without breaking persistent object lookups?

Answers approved by DevExpress Support

created 11 years ago (modified 7 years ago)

Hello Conchur,

To pass changes made in the Elapsed event handler to the main (UI) thread, either use the BeginInvoke method or assign the timer's SynchronizingObject property as shown below:

C#
public class WinViewController1 : ObjectViewController<DetailView, Payment> { System.Timers.Timer timer; protected override void OnActivated() { base.OnActivated(); timer = new System.Timers.Timer(1000); timer.SynchronizingObject = (ISynchronizeInvoke)Frame.Template; timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); timer.Start(); } void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { ((Payment)View.CurrentObject).Rate = DateTime.Now.Second; } protected override void OnDeactivated() { base.OnDeactivated(); timer.Stop(); timer.Dispose(); } }

Feel free to contact us if you need further assistance.

Update:

When using this example in other scenarios, ensure that the Timer.SynchronizingObject property is correctly assigned. Depending on the scenario, it may be necessary to handle the Frame.TemplateChanged event or use the View.Control property in the ViewController.OnViewControlsCreated method.

    Comments (2)

      Thank you, this works perfectly.

      Anatol (DevExpress) 11 years ago

        You are welcome!

        Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

        Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.