Monday, August 30, 2010

Controlling DevExpress XtraGrid Part-3 (The Columns)

Continuning the Controlling XtraGrid Control series..
Contolling DevExpress XtraGrid Part-2 (Master Detail)
Controlling DevExpress AspxGridControl at runtime
Controlling DevExpress XtraGrid Control at runtime

With the great help of DevExpress Support Guys eXpand now has an engine that can push any class property to your model and then using the power of modeldifference module allow you to change its value at runtime.

See for example how simple we have define all the the options of a GridColumn and push them to the model

public interface IModelColumnOptions : IModelColumnOptionsBase {

    IModelGridColumnOptions GridColumnOptions { get; set; }

}

 

public interface IModelGridColumnOptions : IModelNode {

    IModelGridColumnOptionsColumn OptionsColumn { get; set; }

    IModelGridColumnOptionsColumnFilter OptionsFilter { get; set; }

}

 

public interface IModelGridColumnOptionsColumn : IModelNode {

}

 

public interface IModelGridColumnOptionsColumnFilter : IModelNode {

}

 

public class GridColumnOptionsController : ColumnOptionsController<GridColumn, IModelGridColumnOptions>

{

    protected override Func<PropertyInfo, bool> ControlPropertiesFilterPredicate() {

        return info => info.PropertyType == typeof(OptionsColumnFilter) || info.PropertyType == typeof(OptionsColumn);

    }

 

    public override Func<PropertyInfo, bool> DynamicPropertiesFilterPredicate() {

        return info => true;

    }

}

as you can see all above interfaces have no members and are here just to serve their name all the work is done by the base ColumnOptionsController that takes as a generic argument the class we are interested in pushing to the model and provides methods (ControlPropertiesFilterPredicate) to allow us to control the properties that are going to be pushed

image

same process exactly for AspxGridView columns

public interface IModelColumnOptions : IModelColumnOptionsBase

{

    IModelGridColumnOptions GridColumnOptions { get; set; }

}

 

public interface IModelGridColumnOptions : IModelNode

{

    IModelGridViewColumnSettings Settings { get; set; }

}

 

public interface IModelGridViewColumnSettings:IModelNode {

}

 

public class GridColumnOptionsController : ColumnOptionsController<GridViewColumn, IModelGridColumnOptions>

{

    protected override Func<PropertyInfo, bool> ControlPropertiesFilterPredicate() {

        return info => info.PropertyType == typeof(GridViewDataColumnSettings);

    }

 

    public override Func<PropertyInfo, bool> DynamicPropertiesFilterPredicate() {

        return info => true;

    }

}

image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Friday, August 27, 2010

ModelArtifactState

After I posted the Contolling DevExpress XtraGrid Part-2 (Master Detail) I got many requests to speak about how easy will be to make a behaviout conditional so I am going to explain again how ModelArtifact module was build that is based on eXpand logic architecture

Is based on the eXpand Logic architecture and more specifically at eXpand Conditional Logic architecture. That means that Conditional Logic architecture is designed to execute conditional logic rules and from the name of the module one can easily understand that the rules are responsible to change the state of model artifacts, and what are the model artifacts? Controllers and actions.

tell how and when the state is changed

So for all modelartifacts have a common attribute the Module (one can define all controllers or actions in a module or in a regex on modules that the rule will be applied upon)

By using the logic architecture we just need to implement the following interface that describe the above

public interface IArtifactStateRule:IConditionalLogicRule {

    string Module { get; set; }

}

image image

Now for action artifact the implementation will look as (Note IArtifactStateRule base type)

public interface IActionStateRule : IArtifactStateRule {

    IModelAction ActionId { get; set; }

    ActionState ActionState { get; set; }

}

image

as you see we use an Action attribute and an ActionState one, the values of action state are

public enum ActionState {

    Default,

    Disabled,

    Hidden,

    Executed,

    ExecutedAndDisable

}

And for Controller Artifact the implementation will look like (Note IArtifactStateRule base type)

public interface IControllerStateRule : IArtifactStateRule {

    Type ControllerType { get; set; }

    ControllerState ControllerState { get; set; }

}

image

As u see we have the type of the controller that the ControllerState will be applied uppon

the values of controllerState are

public enum ControllerState {

    Default,

    Disabled,

    Enabled

}

if we explore the modelartifact model structure  we see that we have set the rules to be executed at ViewChanging

image

that means that modelartifacts state will change there (eg. controllers,action will be disabled at ViewChanging)

As I say cause of the logic architecture that behavior, that is changing the state of ModelArtifacts can be applied either through model editor as i explain or through attributes on an object

[ControllerStateRule("testId",typeof(DeleteObjectsViewController),"1=1","1=1",ControllerState.Disabled)]

[ActionStateRule("testId","Delete","1=1","1=1",ActionState.Hidden)]

public class LogicRuleDomainObject : BaseObject {

    public LogicRuleDomainObject(Session session) : base(session) {

    }

or through permissions

image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Wednesday, August 25, 2010

Custom pivot sorting

I will start this blog with an embrace to the genius architecture of DevExpress Xaf framework. As the time passes by and you get more experienced in using it you will soon realize that it has teach you to write so declarative code that almost 95% of it is reusable and should go to your base libraries or else to eXpand!!

So the new addition to eXpand has to do with custom pivot sorting .

Say that for a domain model similar to

image

you have design an analysis object using your win UI like

image

image

as you can see Xaf by default is going to sort your products by using the default property of the Product persistent object with is name .

But your client asked you to sort by the Sort property of Product which values can be controlled by him through the UI.

For that reason you could use eXpand.ExpressApp.PivotChart.PivotedProperty.PivotedSortAttribute in combination with eXpand.ExpressApp.PivotChart.PivotedProperty.PivotedPropertyAttribute similar to

[PivotedSort("Product.Name", SortDirection.Ascending,"Product.Sort")]

[PivotedProperty("NewPumpPrices", "Name='Web new pump price analysis'", "Site")]

public Analysis NewPumpAnalysis { get; set; }

 

[Browsable(false)]

public XPCollection<Price> NewPumpPrices {

    get { return PriceBuilder.GetNewPumpPricesWithNoTypeFromTransaction(Session); }

}

and then using also PivotGridOptionsView Settings

image

you could hide the grid headers

image

and by adjusting your layout using Model Editor you can produce a custom sorted web view exactly as your client asked you using only declarative programming approaches!!!

image

Isn't’ that wonderful for your work? If you still cannot think why this is imagine that using worldcreator even your client (no developer) can implement that scenario alone (of course with some guidance from you).

 

That is why i started this blog post with an embrace to Xaf, it just changes the way we used to think about applications!!!!!

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Monday, August 23, 2010

Xaf Models Xaf Models and again Xaf Models

This is a sneak peek for eXpand v10.

Now it is possible to have multiple models per module as shown in the pic bellow

image

The question is how the use them ? I will say a few words about current approaches.

First of all your adiitional models should have Embedded Resource as Build Action

image

Design Time

you could use eXpand Model Editor that is based on Devexpress standalone editor. (See here more info about it here)

image

Now when you hit enter or double click an entry in that list the standalone editor will open up and will compine all models but will add as lastlayer the selected one thus forcing model editor to display that model as diffs (bold), and of course when you save is going to use the selected resource file as well.

Another question will be how to support child models? How for example eXpand Model Editor will now that there is a platform intepented module that also has a additional models?

To solve this one eXpand has introduced the DependentAssembly attribute. So if you apply that attribute at your win module for example like

[assembly: eXpand.Utils.DependentAssembly.DependentAssembly(typeof(PlatformIntepentedModule))]

eXpand will know that in the assembly that PlatformIntepentedModule class is defined may find more additional models to load before the selected one.

ps:models with the same name and path when loaded at runtime will be combined to one model.

With all the above we have cover the design time experince and now we have the power to involve many users messing around with our models without problems with our version control system.

Runtime

To load additional model at runtime since Xaf will not do it by default we have to use the ModelDifference module and read our resources and save them as as ModelDifference objects.

eXpand provided 2 ways of doing that

Load manually using a code similar to

public class ThirdModelStore : eXpand.ExpressApp.ModelDifference.Core.ModelApplicationFromStreamStoreBase

{

    protected override Stream GetStream() {

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

    }

}

for reading the resource file. And by using the code bellow you register the Store to ModelDifference store engine

[ToolboxItemFilter("Xaf.Platform.Win")]

public sealed partial class ExternalApplicationWindowsFormsModule : ModuleBase

{

    public ExternalApplicationWindowsFormsModule()

    {

        InitializeComponent();

    }

    public override void Setup(ApplicationModulesManager moduleManager)

    {

        base.Setup(moduleManager);

 

        var modelDifferenceBaseModule = (ModelDifferenceBaseModule)moduleManager.Modules.Where(

                mbase => typeof(ModelDifferenceBaseModule).IsAssignableFrom(mbase.GetType())).SingleOrDefault();

        if (modelDifferenceBaseModule != null)

            modelDifferenceBaseModule.CreateCustomModelDifferenceStore += ModelDifferenceBaseModuleOnCreateCustomModelDifferenceStore;

    }

 

    void ModelDifferenceBaseModuleOnCreateCustomModelDifferenceStore(object sender, CreateCustomModelDifferenceStoreEventArgs e) {

        e.AddExtraDiffStore(new ThirdModelStore());

    }

}

or by adding an MDO_ prefix to your resource model name.

image

MDO stand for ModelDifferenceOjbect, RDO (Role) and UDO (User) are not supported yet.

Using the above procedures when you go to your modeldifferences listview you are going to see 2 differences object created

image

Now using this powerfull module the things you can do are limited by your imagination.

1.Since those 2 are Application models that mean that when using the editor to change them all changes will be propageted to all users, cause they all use the same database and models are stored there.

image

2.You could combine those models with others (many to many combination) (Combination of models that belong to different application is not supported though)

image

3.You could clone/upcast them them to another type Such as Role Or User

image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Monday, August 16, 2010

Contolling DevExpress XtraGrid Part-2 (Master Detail)

This is a sneak peak for eXpand v10

We have control trhough model all of the options of GridView as shown at  Controlling DevExpress AspxGridControl at runtime 

eXpand had already a very simple implementation of master detail but did not support many levels. Since that implementation was too old i wrote it almost when I started using Xaf I though I give it a try now that I am more experienced so I wrote down some specs about what I wanted

The requirements

  1. Be able to configure the grid views at any level
  2. Be able to control the grid views at any level through controllers
  3. Run Master View actions at child views (eg.delete,save etc)
  4. Support different detailviews per master row
  5. Only special user roles should have the permission to see master detail views

1. Be able to configure the grid views at any level

So say we have a listview that contains a master grid view , our goal will be to expose all associated collections of current type to the model and allow the user to associated a view for each member

That can be done by extending IModelListView with the bellow interface

public interface IMasterDetailRule  {

    IModelListView ChildListView { get; set; }

    IModelMember CollectionMember { get; set; }

}

As you see I have expose a CollectionMember that will have all collections of Master object and ChildListView and now I can associate a Member with a view for a given listview. Then if i go to the ChildListView and set again the values of CollectionMember ,ChildListView I almost support inheritance configuration and by using each listview model attributes I can configure each child list view.

Also if I could assign multiple IMasterDetailRule  to the listview I could support XtraGrid DetailTabs feature and along with eXpand GridViewOptions feature I think I have fully define how the configuration will look .

2. Be able to control the grid views at any level through controllers

That will really mean that i have to create a listview and a frame for each child grid view. That could mean that I have to use some code similar to

CollectionSourceBase collectionSourceBase = _xafApplication.CreateCollectionSource(_objectSpace.CreateNestedObjectSpace(), type, modelListView.Id);

ListView listView = _xafApplication.CreateListView(modelListView, collectionSourceBase, true);

that will create a listview for me along with a GridListEditor and when I add some code like

Window window = _xafApplication.CreateWindow(TemplateContext.View, null, true, true);

it will create a new frame /window for me. And finally when i add the following code

window.SetView(listView);

xaf will create all controls and run all controllers for the new created childlist view. What's left is since I have created all controls/gridlisteditor for the child listview to grab child GridListEditor GridView and associate it as a child grid view of my master GridView.

3. Run Master View actions at child views (eg.delete,save etc)

Master actions will run on the master context which is the Master Listview and will use as CurrentObject,SelectedObjetcs values taken from GridListEditor. So what I have to do is create my own GridListEditor set it as default Xaf GridListEditor override the methods that are responsible for returning the values of CurrentObject,SelectedObjetcs and return values taken from the focused child gridview.

4. Support different detailviews per master row

Since we have a behaviour (child gridview creation) defined and want to make them conditional its time for eXpand logic architecture . So lets redefine the IMasterDetailRule  according to the logic architecture

public interface IMasterDetailRule : IConditionalLogicRule {

    IModelListView ChildListView { get; set; }

    IModelMember CollectionMember { get; set; }

}

inherit from ConditionalLogicRuleViewController and create a list of active IMasterDetailRules that the controller we have create at step 2 and is responsible for associating the gridview  will use .

5. Only special user roles should have the permission to see master detail views

I really not have to do much here since logic architecture supports that be default.

The result? A new conditional module for eXpand called MasterDetail,MasterDetail.Win (2 assemblies)

For example to define a simple 3 level inheritance between Customer,Order,OrderLines you have to create the following rules

image

configure your Customer_ListView

OptionsDetail attributes as

image

and show the detail using OptionsView attributes

image

And do exactly the same for your Orders_ListView .

Or if you like to create a conditional child gridview for example display a different Orders child view for Customers that live in Paris you could create a rule similar to

image

That rule will run for MDCDVCustomer_ListView and it will create a child gridview from the model of MDCDVOrder_ListView_For_Paris listview only for customers that live in Paris (see NormalCriteria attribute).

As I say all that conditional stuff happens cause we have use eXpand logic architecture and that means that we can use instead of model editors, class attributes to define our rules like bellow

[MasterDetail("MDCustomer_Orders", "1=1", "MDOrder_ListView","Orders",View = "MDCustomer_ListView")]

public class MDCustomer : CustomerBase {

    public MDCustomer(Session session) : base(session) {

    }

[MasterDetail("MDOrder_OrderLines", "1=1", "MDOrderLine_ListView", "OrderLines",View = "MDOrder_ListView")]

    public class MDOrder : OrderBase {

        MDCustomer _customer;

or permissions of we want our rules to be applied only to specified user roles

image

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

Tuesday, August 3, 2010

3 pictures 3000 words!!!

The last few months i have been silent but not lazy at all so I post the next 3 pictures to give you an idea what eXpand will deliver by v10

 image

image

image

So what you think? I just can’t wait to finish.

Subscribe to XAF feed
Subscribe to community feed

DiggIt!