Monday, December 20, 2010

eXpand gets a Russian ISBN

Continuing my effort to introduce eXpand framework to the world and with the help of some eXpand framework funs that want to remain anonymous I got invited to write an article for the Second International Scientific-Practical Conference Proceedings hosted at http://objectsystems.ru/ and edited by Pavel P. Oleynik

The title of my article is Application frameworks in the real world and in a few words I explain the idea behind eXpand framework, how we have extend Devexpress XAF framework and speak about eXpand architecture. The paper can be very useful to all XAF/eXpand users! (pages 9-15 English)

The collection can be found at Object Systems – 2010 (Winter session), The Second International Scientific-Practical Conference Proceedings, Russia, Rostov-on-Don, 10-12 November 2010. Edited by Pavel P. Oleynik

cert_ru

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Monday, December 6, 2010

Context programming

I ll start this post with a phrase : WE HAVE TO REMEMBER TO NOT REINVENT THE WHEEL .

Why I say that?

XAF with the help of eXpand  is now a very mature framework. Almost all the tools required for build LOB applications are here. XAF has many ruling engines (Validation,EditorState,Appearence) and eXpand also the same (AdditionalViewControls, ModelArtifactState, MasterDetail, ConditionalDetailViews).

All the above engines provide a way to describe behaviors using rules and they operate over certain Contexts. What is a context some of you may ask. The answer is simple, context means the “when” the rule is going to be evaluated. For example Validation rules have 2 predefined contexts , those are Save,Delete.

I am going to give an example of how powerful a context is . Let say we have a Customer-Order relationship and we have 2 cases like the following

  • First record of Customer Orders cannot be deleted.
  • Only the last record of Customer Orders can be deleted

So what we need to design the above rules? First of all since both cases speak about the index of Order record we need to adjust our Order class to provide that info. If you use eXpand the code should be similar to

image

And the second step is to decorate the Orders collection of the Customer class with 2 RuleValueComparison attributes

image
As you see we have 2 rules that operate on the Delete context and check the value of the Sequence property against an Aggregation. That is a very powerful approach cause we used the Validation engine that is fully tested and we just describe our scenario declaratively using attributes. In fact we could do the same at runtime using the Model editor.

But let me add 2 more cases

  • Only the last record of Customer Orders can be cloned
  • Only the last record of Customer Orders can be edited

From a first look seems that validation engine cannot help us here, but if we think again we will notice that only the deleted word changed to cloned/edited. In other words only the context change so we could just add the “Cloned;Edited” context to our last rule

image

 

and write some code that will force the Validation engine to execute for our custom contexts as well.

image

 

The only caveat here is that you have to manually write the above code for every action you want to force the engine to run. But if you are using eXpand you not need the above handling, you could just use the Ids of your actions as Context names and eXpand will force the validation engine to execute

image

 

The above code can be used with eXpand 10.2.3 or newer and is hosted at eXpand.ExpressApp.Validation module

http://expandframework.com/download.html

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Thursday, December 2, 2010

Modular User interface

I was discussing with a friend some days ago about his project requirements.

  • Solution had roles but they where fixed (Like Manager, Receptionist etc)
  • Different UI is needed for each role
  • At runtime there should be a way to change the UI using an action

He told me that he was aware of eXpand Role models and he thought that they could help his case.

For those of you that are XAF newbies a XAF model is really a description of your application structure /behavior over a xafml file

Sure I told him ModelDifference module can help , however the approach would be slightly different from the one you had in your mind and here is why:

Although the application have roles since there is no login (wanted to change UI from an action ) we could not use ModelDifference Role models.  What I suggested was to use disabled application models and then use eXpand api to just enabled them at runtime. In fact we could create as many application models as the fixed roles are in the updater with a code similar to

    public class Updater : ModuleUpdater {

        public Updater(Session session, Version currentDBVersion) : base(session, currentDBVersion) { }

        public override void UpdateDatabaseAfterUpdateSchema() {

            base.UpdateDatabaseAfterUpdateSchema();

            CreateDisabledModelDifferenceObject(typeof(ManagerModelStore));

            CreateDisabledModelDifferenceObject(typeof(ReceptionistModelStore));

        }

 

        void CreateDisabledModelDifferenceObject(Type storeBaseType) {

            var modelDifferenceObject = Session.FindObject<ModelDifferenceObject>(o => o.Name == storeBaseType.Name);

            if (modelDifferenceObject == null) {

                ModelDifferenceObject differenceObject = new ModelDifferenceObject(Session).InitializeMembers(storeBaseType.Name);

                var layer = new ModelApplicationBuilder(differenceObject.PersistentApplication.ExecutableName).GetLayer(storeBaseType);

                differenceObject.CreateAspects(layer);

                differenceObject.Disabled = true;

                differenceObject.Save();

            }

        }

    }

 

also we need 2 modelstores that will point to our Manager,Receptionist models

 

    public class ReceptionistModelStore : ModelApplicationFromStreamStoreBase {

        protected override Stream GetStream() {

            return GetType().Assembly.GetManifestResourceStream(GetType(), "Receptionist.xafml");

        }

    }

    public class ManagerModelStore : ModelApplicationFromStreamStoreBase {

        protected override Stream GetStream() {

            return GetType().Assembly.GetManifestResourceStream(GetType(), "Manager.xafml");

        }

    }

  

2 design time models Manager.xafml,Receptionist.xafml

image

 

of course eXpand Model Editor addin in order to be able to modify the models

image

 

The code we wrote at the update will create 2 disabled application models in our modeldifference listview as shown bellow

image

Disabled models means that they wont load when application starts. In order to load them on demand we have to create some actions and use ModelDifference api. A simple controller like the one bellow will do the job.

 

using DevExpress.ExpressApp;

using DevExpress.ExpressApp.Actions;

using DevExpress.ExpressApp.Win;

using DevExpress.Persistent.Base;

using Xpand.ExpressApp.ModelDifference.Core;

 

namespace Solution1.Module.Win {

    public class ActionsController : ViewController {

 

        public ActionsController() {

            var managerAction = new SimpleAction(this, "Manager", PredefinedCategory.View);

            managerAction.Execute += ManagerActionOnExecute;

            var receptionistAction = new SimpleAction(this, "Receptionist", PredefinedCategory.View);

            receptionistAction.Execute += ReceptionistActionOnExecute;

        }

 

        void ReceptionistActionOnExecute(object sender, SimpleActionExecuteEventArgs simpleActionExecuteEventArgs) {

            var modelApplicationLoader = new ModelApplicationLoader();

            modelApplicationLoader.EnableModel(o => o.Name == "ReceptionistModelStore", new[] { "ManagerModelStore" });

            RecreateWindows();

        }

 

        void ManagerActionOnExecute(object sender, SimpleActionExecuteEventArgs simpleActionExecuteEventArgs) {

            var modelApplicationLoader = new ModelApplicationLoader();

            modelApplicationLoader.EnableModel(o => o.Name == "ManagerModelStore", new[] { "ReceptionistModelStore" });

            RecreateWindows();

        }

 

        void RecreateWindows() {

            var showViewStrategyBase = (WinShowViewStrategyBase)Application.ShowViewStrategy;

            showViewStrategyBase.CloseAllWindows();

            showViewStrategyBase.ShowStartupWindow();

        }

    }

}

and that was it!!
The above solution needs eXpand v10.1.8 or newer http://expandframework.com/download.html

Subscribe to XAF feed
Subscribe to community feed

DiggIt!