When the Open Related Object action is executed, DetailView is shown. After changing data and executing Save And Close Action in this DetailView, the source View shows a corresponding reference property value unchanged.
How to refresh data in the View after the Open Related Record action is executed
Answers approved by DevExpress Support
To show changes after an object's DetailView is closed, use the following workaround:
C#using System;
using System.Collections.Generic;
using System.Linq;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Win.Editors;
using DevExpress.XtraGrid.Columns;
using DevExpress.ExpressApp.Win.SystemModule;
using DevExpress.ExpressApp.Editors;
namespace MainDemo.Module.Win.Controllers {
class RefreshDataInOwnerObjectViewController : ViewController<DetailView> {
private View ownerView;
private object objectToOpen;
public RefreshDataInOwnerObjectViewController(View ownerView, object objectToOpen) : base() {
this.ownerView = ownerView;
this.objectToOpen = objectToOpen;
}
protected override void OnActivated() {
base.OnActivated();
ObjectSpace.Committed += ObjectSpace_Committed;
}
private void ObjectSpace_Committed(object sender, EventArgs e) {
if(ownerView == null || ownerView.IsDisposed) {
return;
}
ownerView.ObjectSpace.ReloadObject(objectToOpen);
if(ownerView is ListView) {
ListView listView = (ListView)ownerView;
if(listView.Editor is GridListEditor) {
GridListEditor gridListEditor = ((GridListEditor)listView.Editor);
//refresh all visible rows in a grid control
gridListEditor.GridView.LayoutChanged();
}
}
if(ownerView is DetailView) {
DetailView detailView = (DetailView)ownerView;
//refresh a display text at property editors
IEnumerable<IObjectPropertyEditor> objectPropertyEditors = detailView.Items.OfType<IObjectPropertyEditor>();
foreach(PropertyEditor objectPropertyEditor in objectPropertyEditors) {
if(objectPropertyEditor.PropertyValue == objectToOpen) {
objectPropertyEditor.Refresh();
}
}
IEnumerable<LookupPropertyEditor> lookupPropertiesEditors = detailView.Items.OfType<LookupPropertyEditor>();
foreach(LookupPropertyEditor lookupPropertyEditor in lookupPropertiesEditors) {
if(lookupPropertyEditor.PropertyValue == objectToOpen) {
lookupPropertyEditor.Refresh();
}
}
}
}
protected override void OnDeactivated() {
base.OnDeactivated();
ObjectSpace.Committed -= ObjectSpace_Committed;
}
}
public class RefreshViewFromRelatedObjectDetailViewController : ViewController {
public RefreshViewFromRelatedObjectDetailViewController() : base() { }
protected override void OnActivated() {
base.OnActivated();
OpenObjectController openObjectController = Frame.GetController<OpenObjectController>();
if(openObjectController != null) {
openObjectController.CustomOpenObject += OpenObjectController_CustomOpenObject;
}
}
protected override void OnDeactivated() {
OpenObjectController openObjectController = Frame.GetController<OpenObjectController>();
if(openObjectController != null) {
openObjectController.CustomOpenObject -= OpenObjectController_CustomOpenObject;
}
base.OnDeactivated();
}
private void OpenObjectController_CustomOpenObject(object sender, CustomOpenObjectEventArgs e) {
e.InnerArgs.ShowViewParameters.Controllers.Add(new RefreshDataInOwnerObjectViewController(View, e.ObjectToOpen));
}
}
}
Thanks,
Nat.
Thanks, Uriah,
That seems to do the trick. I'll keep an eye out on this. Really seems like this should just be the default behavior.
Thank you for the clarification. I added this code to the answer above so that others customers who will use this code will not experience the same issue.
To be honest I never noticed this problem, until I read this ticket and tested it. This is the kind of detail we expect xaf to just work. I agree this should be the default behavior, but the provided solution works perfectly. Thanks.
For those who already have a derived OpenObjectController, you can avoid the second controller altogether, by doing something like this:
C#protected override void OnCustomOpenObject(CustomOpenObjectEventArgs e)
{
base.OnCustomOpenObject(e);
e.InnerArgs.ShowViewParameters.Controllers.Add(new RefreshDataInOwnerObjectViewController(View, e.ObjectToOpen));
}