Thursday, October 25, 2012
Passing XafApplication, ObjectSpace and other data into custom non-XAF forms
Today I came across this Support Center ticket and it forced me to blog about possible solutions to this task, because it is quite common and may be interesting for others.
First, let me stop for a while and describe when a custom form may want to use this information. Imagine that you have a data-aware custom form (e.g., a grid that displays persons) and you want to populate it with data from your database. In order to do this, and if you use the traditional development approach and XPO as a data layer, you will most likely configure your XPO data layer and then create a Session to access your data. When using XAF, this work already done for you by the framework (you just need to specify a required connection string via the designer or in configuration file). So, you do not need to mess with the same connection string in your custom form, but rather use a ready-to-use Session object that already points to the main application database. You can get the XPO's Session object via the XPObjectSpace.Session property. People who are not familiar with XAF should know that ObjectSpace is a ORM-independent entity, data context that provides access to data in XAF applications. There are different implementations of ObjectSpace for different ORMs, e.g. XPObjectSpace for XPO and EFObjectSpace for EF.
Of course, in addition to quering data, you may also use other XafApplication services in your custom forms. For instance, read some settings from the Application Model - a universal metadata and settings store for XAF applications.
Now, let's talk about passing this data into custom forms.
When implementing your custom form class, you should supply all the external information for its normal operation. Technically, you can do this by introducing special public properties (that will hold required data) and assign them after the form creation. A better and more natural solution would be introducing new constructors with required parameters for your form.
To display a custom form in XAF, you can use a Controller with an Action, e.g. as described here. From this Controller you always have access to the XafApplication object via the Application property. So, you can pass it as a parameter into your custom form. This solution is demonstrated in this Code Central example.
But what to do, if you do not use controllers to invoke custom forms/user controls? How to access XafApplication in this case?
It all depends on your scenario. For instance, if you implement a custom PropertyEditor/ViewItem or ListEditor, then you can implement the IComplexPropertyEditor/IComplexListEditor interfaces by your custom classes. As a result, the Setup method provided as part of these interfaces will be automatically called by XAF and you wil receive required parameters (e.g., ObjectSpace, XafApplication) into your classes for further reuse.
If your scenario is different, you can implement a static helper class that will hold XafApplication (you will have to first initialize it in the Main method, though) so that you can access it from anywhere in your code. It is a bit naive, but is also a good and easy to implement solution.
BTW, I started to think about introducing a static Instance property (like in XAF Web UI) into the WinApplication class, so that you can easily access it from anywhere using the following code:
I think that it may simplify lives of many not so experienced XAF devs (so that they are not forced to implement sophisticated solutions like the ones I described earlier). What do you think?;-)