Search This Blog

Wednesday, May 14, 2014

A very interesting way to update and display a persistent property via a non-persistent one

Scenario:

A customer wanted to extend the User class with additional property that would store the information about the startup View for this user when it launches the app. This is very similar to the StartupNavigationItem attribute, which is present for the NavigationItems node in the application model, but with the difference that application users should be able to modify this via the standard XAF CRUD forms.

How would you normally approach this?;-)

Possible solutions

At this time, I can think of at least three good options for accomplishing this task: two platform-dependent and one platform-agnostic, which I am going to detail later in this post. In all three cases we will extend our business class with a string property that would store this startup View information (its identifier) in the database.



Platform-dependent

First, let's discuss the two most obvious platform-dependent options:
1. Implement a custom PropertyEditor that would provide a drop down with a list of available startup Views, probably taken from the NavigationItems node in the application model. Good examples of such custom editors can be found at the bottom of the Implement Custom Property Editors article.
2. Use the standard XAF PropertyEditor for strings, but customize its PredefinedValues property through a ViewController.

Platform-agnostic

3. The idea is to define a non-persistent POCO that would represent the information about Views in the UI. This class should also be decorated with the DomainComponent or NonPersistent attributes to tell XAF to recognize this POCO as a business class and thus generate the application model for it:

    [DomainComponent, XafDefaultProperty("DisplayName")]
    public class NonPersistentView {
        public string Id { get; set; }
        public string DisplayName { get; set; }
    }

Then, add a non-persistent property of this POCO type and modify its setter to update the persistent property based on the selected value. As far as XAF is concerned, this non-persistent property is a regular reference/lookup property, which will be presented through the standard LookupPropertyEditor and ASPxPropertyEditor in the UI. That said, we can also use the DataSourceProperty attribute to provide a data source for our lookup editor, since it is non-persistent and thus is not getting any data from the database by default:

[Persistent("StartupView")]
private string startupViewStored;
private NonPersistentView _StartupViewForDisplay;
[NonPersistent, DataSourceProperty("ViewsDataSource"), XafDisplayName("Startup View")]
public NonPersistentView StartupViewForDisplay {
    get {
        if(_StartupViewForDisplay == null && !string.IsNullOrEmpty(startupViewStored)) {
            _StartupViewForDisplay = ViewsDataSource.Single(v => v.Id == startupViewStored);
        }
        return _StartupViewForDisplay; 
    }
    set {
        SetPropertyValue<NonPersistentView>("StartupViewForDisplay", ref _StartupViewForDisplay, value);
        if(!IsLoading && !IsSaving) {
            startupViewStored = value != null ? value.Id : string.Empty;
            OnChanged("startupViewStored");
        }
    }
}
private List<NonPersistentView> _ViewsDataSource = null;
protected IList<NonPersistentView> ViewsDataSource {
    get {
        if(_ViewsDataSource == null) {
            _ViewsDataSource = new List<NonPersistentView>();
            _ViewsDataSource.Add(new NonPersistentView() { Id = "Contact_ListView", DisplayName = "Contacts" });
            _ViewsDataSource.Add(new NonPersistentView() { Id = "DemoTask_ListView", DisplayName = "Tasks" });
            // You can load this info from the Application Model through the CaptionHelper.ApplicationModel property, if necessary.
        }
        return _ViewsDataSource;
    }
}

As a result, we will have only platform-independent code and this will also look nicely in the UI:



You can find another example of this approach in the Using a built-in lookup editor based on values from another table for editing simple property types blog post.

I hope you liked this trick and can use it for similar tasks.

1 comment:

  1. You can find another application of this approach in http://stackoverflow.com/questions/24824031/devexpress-xaf-class-property-datasource-filtering/25011246#25011246

    ReplyDelete