Archive

Posts Tagged ‘Ext.Net’

[Ext.Net] Helper pour la création d’un GridPanel

Bon, finalement, je l’ai dis mais pas fais, parce que j’ai fais le gros glandeur pendant mes vacances… Mais que c’est bon ! Bref

Série de billets sur les helpers que j’ai réalisés autour d’Ext.Net. Le sommaire référençant les helpers est ici : Présentation des helpers.

Dans ma mission, on a des grilles. Un tas de grilles. Énormément de grilles… De quoi donner un peu la nausée, parfois, mais comme c’est le client qui veut !

La problématique était donc la suivante :

  • On a beaucoup de grilles, on doit pouvoir en faire PLEIN de façon simple
  • Les listes contiennent parfois beaucoup d’objets
  • Chaque objet contient des objets, qui contient des obj…
  • Chaque objet peut avoir un bon nombre de propriétés (parfois des agrégations en fonction d’autres propriétés…)

Résultat des courses, je me colle à faire un composant Ext.NET en lecture seule (ça, c’est important). Qui doit gérer pas mal d’objets avec beaucoup de propriétés. Ces deux points sont importants puisque le tout allant être sérialisé, le premier jet à directement fait planter IE parce que la source HTML était trop grosse (bah oui, Ext.NET sérialise tout ou alors que les propriétés simples à la racine de l’objet…).

Je prends donc mon objet :

public class MySampleObject
{
    public String StringProperty { get; set; }
    public DateTime DateProperty { get; set; }
    public Int32 IntProperty { get; set; }
    public Single FloatProperty { get; set; }
    public String DoNotShowProperty { get; set; }
    public Boolean BoolProperty { get; set; }
    public String Currency { get; set; }
    public MySampleObject InnerObject { get; set; }
    public Dictionary<string, Double> Amount { get; set; }
}

Dans ma grille, je dois pouvoir afficher le montant (propriété Amount, de la forme Amout[« USD »] ou Amount[« EUR »]) en fonction de la monnaie (propriété Currency), mais aussi l’afficher que en Euro.
Dans le même temps, je dois pouvoir aller chercher le libellé correspondant à la monnaire (EUR => Euro; USD => Dollar; BOB => Boliviano ;)).
Je dois aussi pouvoir aller chercher un propriété d’un objet enfant, etc.
En gros, plein plein de cas.

Pour ce faire, j’ai choisis une méthode assez simple : je vais utiliser la réflexion pour créer un dictionnaire de données que je vais binder au contrôle.
Plusieurs avantages :

  • Je ne vais mettre que les données dont j’ai besoin dans le dictionnaire, donc la source sera allégée
  • Je peux conditionner des affichages en fonction d’autres données
  • Je peux formatter mes données en .Net et non plus en JS

Alors, comment ça se passe, en pratique ?

Etape 1 : la configuration de la grille
Cette étape est totalement mutualisable dans le cas de plusieurs grilles. Il faudra UNIQUEMENT redéfinir l’ID des grilles.
Exemple :

ExtGridEntity configuration = new ExtGridEntity("MyGridExtPanel", columns)
{
    AutoExpandColumn = 0,
    ColTooltipIsColName = true,
    Height = 400,
    PageSize = 20,
    PagingPosition = PagingPosition.Both,
    Sortable = true,
    Width = 500
};

On peut donc faire une méthode assez basique qui prend en paramètre un string représentant l’ID et qui renvoit un objet ExtGridEntity.

Etape 2 : lister les colonnes
Le nerf du contrôle, si je puis dire.
Là, on va lister toutes les colonnes, dire où sont les données, comment les récupérer, les formatter…

List<ExtGridColumn> columns = new List<ExtGridColumn>()
{
    new ExtGridColumn("One", "Currency"),
    new ExtGridColumn("Two", "IntProperty", DataType.Int),
    new ExtGridColumn("Three", "FloatProperty", DataType.Float),
    new ExtGridColumn("Four", "DateProperty", DataType.Date),
    new ExtGridColumn("Five", "BoolProperty", DataType.Boolean),
    new ExtGridColumn("Six", "InnerObject.StringProperty"),
    new ExtGridColumn("Seven", "InnerObject.InnerObject.StringProperty"),
    new ExtGridColumn("Eight", "Amount", "Currency", false),
    new ExtGridColumn("Nine", "Amount", "USD", true),
    new ExtGridColumn("Ten", "InnerObject.StringProperty", "<a href='Currency.aspx={One}'>Info of currency: {One}</a>"),
    new ExtGridColumn("Eleven", GetCurrencyLabel, false)
};
columns[1].FormatDataMethod = FormatInt32;
columns[3].FormatDataMethod = FormatDateTime;

Avec les différents constructeurs, on peut par exemple faire en sorte que la colonne Eight affiche le montant de la monnaie courante  (propriété Currency) alors que la colonne Nine affiche toujours le montant en USD.
On peut aussi voir de l’injection de HTML pour créer un lien, l’utilisation d’une méthode pour récupérer les données (colonne Eleven) ou encore des méthodes pour formatter les données (en dehors de la construction de la liste).

Etape 3 : afficher le composant

ExtGridView<MySampleObject> gridPanel = new ExtGridView<MySampleObject>();
gridPanel.SetDataAndConfiguration(configuration, data, GridContainer);

L’objet configuration est celui de l’étape 1. L’objet data est une simple collection (IList<>) contenant les données. Enfin, GridContainer est simplement la div (runat= »server ») dans laquelle insérer la grille.
Le tout est à placer dans un évènement du type Page_Load ou autre et…le tour est joué !

On obtient donc une grille avec toutes nos données, bien formattée et tout !

Publicités
Catégories :.Net, ASP.Net, C#, Ext.Net

[Ext.Net] Helper pour la création d’une ComboBox

Série de billets sur les helpers que j’ai réalisés autour d’Ext.Net. Le sommaire référençant les helpers est ici : Présentation des helpers.

Avec Ext.Net, il y a plusieurs types de Combobox disponibles.
Pour ma part, j’ai pris la plus simple : celle qui affiche le contenu d’une liste dont le contenu est connu avant la création de la combo.

En pratique, cela veut dire que, dans la page, j’ organise le code comme il suit :

Etape 1 : déclaration des combobox comme propriétés de la page (du user control)

private ExtComboBox combo1;

Etape 2 : configurer la combobox

private ExtComboEntity GetConfigComboBox(int id)
{
    return new ExtComboEntity()
    {
        ComboID = String.Concat("Combobox", id),
        Resizable = true,
        DisplayField = "StringProperty",
        ValueField = "IntProperty",
        EmptyText = "Select value...",
        AllowRemove = true
    };
}

Note : normalement, la propriété EmptyText doit pointer vers une ressource (*.resx / *.resources), mais pour les exemples, je suis passé outre (voir solution d’exemples).

Etape 3 : dans l’évènement OnInit : création du contrôle (constructeur et appel de la méthode SetDataAndConfiguration)

combo1 = new ExtComboBox();
combo1.SetDataAndConfiguration(GetConfigComboBox(1), data.Take(10).ToList(), Combobox1Container);

Etape 4 : dans l’évènement Page_Load : présélection des champs

combo1.SelectedText = "I am property number 9";

En terme de fonctionnement interne, la liste passée en paramètre est transformée en une liste générique de type AnonymousObject.
En effet, j’ai dis à l’occasion de la présentation du helper pour le store que TOUT l’objet est sérialisé.
Dans mon exemple (voir le code sur GitHub), j’utilise un objet MySampleObject qui contient quatre propriétés. Si je laisse Ext.Net le sérialiser, j’aurais dans ma source les quatre propriétés.
A mon sens, cela pose deux problèmes majeurs : le poids de la page qui est chargée inutilement et, plus grave, une possible faille de sécurité.
Donc, avec un peu de réflexion (dans tous les sens du terme), il est possible de transformer, mon proxy est donc pas mal allégé.

new Ext.data.PagingMemoryProxy(
	[
	{"Text":"I am property number 0","Value":"0"},
	{"Text":"I am property number 1","Value":"1"},
	{"Text":"I am property number 2","Value":"2"},
	{"Text":"I am property number 3","Value":"3"}
	[...]

Au lieu de :

new Ext.data.PagingMemoryProxy(
	[
	{"StringProperty":"I am property number 0","DateProperty":"1946-01-15T10:13:50","IntProperty":0,"DoNotShowProperty":"I am the hidden one."},
	{"StringProperty":"I am property number 1","DateProperty":"1982-09-13T22:33:58","IntProperty":1,"DoNotShowProperty":"I am the hidden one."},
	{"StringProperty":"I am property number 2","DateProperty":"1960-02-21T22:15:14","IntProperty":2,"DoNotShowProperty":"I am the hidden one."},
	{"StringProperty":"I am property number 3","DateProperty":"1944-01-20T09:34:41","IntProperty":3,"DoNotShowProperty":"I am the hidden one."},
	[...]
Catégories :.Net, ASP.Net, C#, Ext.Net

[Ext.Net] Présentation des helpers

Ce billet sera relativement court, il a pour but premier de poser la problématique autour de laquelle tournera les suivants.

Sommaire des billets :

Les sources et exemples d’utilisations peuvent être trouvés sur Github.

J’ai déjà brièvement parlé d’Ext.Net, mais je vais faire un rappel ici.

Donc, Ext.Net se base sur le Framework Javascript ExtJS. Il a pour but de mettre à disposition des composants utilisables aisément afin de créer des interfaces web riches. Il suffit simplement de référencer les DLL qui conviennent et c’est tout, rien de plus simple.
Au sein du code, on va donc manipuler des balises à l’instar des balies <asp:…/>.

Voici deux exemples simplistes :

    <ext:ImageButton
        runat="server"
        ImageUrl="button.gif"
        OverImageUrl="overButton.gif"
        DisabledImageUrl="disabled.gif"
        PressedImageUrl="pressed.gif">
        <DirectEvents>
            <Click OnEvent="Button_Click" />
        </DirectEvents>
    </ext:ImageButton>

 

<ext:SpinnerField ID="SpinnerField1" runat="server" FieldLabel="Age" />

Comme on peut le voir, c’est assez simple (simpliste).
Par contre, dès que l’on veut utiliser des composants un peu plus complexes, comme un GridPanel, alors le code ASPX est bien plus long à faire.

La problématique qui s’est posée à moi était simple : sur un projet faisant la part belle au reporting sous forme de tableaux, j’avais un nombre assez considérable de GridPanel. Et comme je suis d’un naturel assez fainéant, j’ai préféré investir un peu de temps à créer un helper.
L’avantage est de pouvoir créer un nombre très important de GridPanel sans gros efforts et surtout de tout gérer dans le code C#, ce qui me permet donc de satisfaire à d’autres besoins qui sont, entre autres, d’avoir un même tableau avec les mêmes données, mais des colonnes affichées ou masquées suivant qui les voit.

Catégories :.Net, ASP.Net, C#, Ext.Net

[Ext.Net] Helper pour la création du store

Série de billets sur les helpers que j’ai réalisés autour d’Ext.Net. Le sommaire référençant les helpers est ici : Présentation des helpers.

La première chose à créer, lorsque l’on veut créer des composants avec des données, c’est le store.

Déjà, qu’est ce que c’est le store.
Le store, c’est comme une DataSource, ça permet de stocker les données (dans notre cas, des données sérialisées).
L’inconvénient, c’est que TOUT le store est stocké dans la page.

Prenons un exemple.
Je souhaite utiliser un GridPanel pour afficher les données d’une liste générique de type :

    public class MySampleObject
    {
        public String StringProperty { get; set; }
        public DateTime DateProperty { get; set; }
        public Int32 IntProperty { get; set; }
        public String DoNotShowProperty { get; set; }
    }

Dans la source de la page, on aura :

		[...Extrait partiel...]

this.MainContent_MyGridExtPanelStoreId=new Ext.ux.data.PagingStore(
	{
	proxyId:"MainContent_MyGridExtPanelStoreId",
	autoLoad:true,
	reader:new Ext.data.JsonReader(
		{
		fields:[
			{name:"StringProperty"},
			{name:"IntProperty",type:"int"},
			{name:"DateProperty",type:"date",dateFormat:"Y-m-dTh:i:s"}
			]
		}),
	directEventConfig:{},
	proxy:new Ext.data.PagingMemoryProxy(
		[
		{"StringProperty":"I am property number 0","DateProperty":"1988-03-01T06:53:34","IntProperty":746583876,"DoNotShowProperty":"I am the hidden one."},
		{"StringProperty":"I am property number 1","DateProperty":"1944-04-13T21:10:31","IntProperty":1822087014,"DoNotShowProperty":"I am the hidden one."},
		{"StringProperty":"I am property number 2","DateProperty":"2000-06-22T14:37:03","IntProperty":1922942219,"DoNotShowProperty":"I am the hidden one."}

		[...Extrait partiel...]

Expliquons un peu cet extrait :
J’ai créé un store (type : PagingStore; id : MainContent_MyGridExtPanelStoreId).
Le reader utilisé est un JsonReader, c’est lui qui s’occupe de la lecture des données.
Au sein du reader, on référence trois colonnes (fields) , se sont les propriétés à afficher :  StringProperty, IntProperty (de type int dans la grille) et DateProperty (de type date dans la grille et avec le format spécifié).
Enfin, les données à proprement parlées sont stockée dans la page (PagingMemoryProxy, à moins de faire appel à un handler).

Mon objet contient plus de champ, il y a la propriété DoNotShowProperty que je ne souhaite pas afficher.
Mais comme c’est l’objet ENTIER qui est sérialisé, il convient de faire TRES attention aux objets utilisés (au même titre q’une page d’erreur affichant du code, cela peut être une faille de sécurité).

Ainsi, je conseillerais d’utiliser des objets « présentation », c’est à dire des objets minimalistes avec uniquement les champs que l’on souhaite afficher (mais qui n’hérite pas des objets métiers, sinon on en revient au même problème…).

Le deuxième effet kiss cool, c’est que comme l’objet est sérialisé (et ça, on y peut rien), il faut bien prévoir que toutes les propriétés de l’objet puissent être sérialisée.

A noter que l’attribut XmlIgnore n’est pas pris en compte.

Pour créer le store, j’utilise donc la classe suivante :

public class StoreFactory
{
    public static Ext.Net.Store Create(String id, JsonReader jsonReader, IList data, String groupByField)
    {
        // Création du Store
        Ext.Net.Store store = new Ext.Net.Store();
        store.ID = id;
        store.Reader.Add(jsonReader);
        store.SerializationMode = SerializationMode.Complex;
        // Groupement sur les entrées
        if (!String.IsNullOrEmpty(groupByField))
            store.GroupField = groupByField;

        store.AutoLoad = true;
        store.AutoDataBind = true;
        store.RemoteSort = false;
        store.RemotePaging = false;

        store.DataSource = data;
        store.DataBind();

        return store;
    }
    public static Ext.Net.Store Create(String id, JsonReader jsonReader, IList data)
    {
        return Create(id, jsonReader, data, null);
    }
}
Catégories :.Net, ASP.Net, C#, Ext.Net