Fermer

octobre 21, 2019

Personnalisation de la création de vos nœuds TreeView


Le TreeView dans Telerik UI for Blazor vous permet de contrôler quand et comment chaque ensemble de nœuds est chargé. Cela vous permet non seulement de contrôler le mode de chargement des nœuds, mais également d'améliorer les performances de votre page.

L'arborescence dans l'interface utilisateur Telerik pour Blazor vous permet de décider de ce qui se passe lorsqu'un nœud est développé – Les nœuds ajoutés à votre arborescence sont récupérés.

Le composant Telerik TreeView facilite l'extraction de données d'une base de données et leur chargement dans TreeView. Mais que se passe-t-il si vos données ne se trouvent pas dans une base de données ou si vous souhaitez les «masquer» avant de les afficher ou si le processus de récupération de vos nœuds est en quelque sorte «compliqué»? TreeView vous permet de récupérer les données de vos nœuds en fournissant une méthode de chargement des données associées basée sur un code.

Cette stratégie d'extraction de nœuds en cas de besoin peut également vous aider à améliorer les performances. Si, par exemple, vous savez que la plupart du temps, la plupart des nœuds de votre arborescence ne seront pas développés, cette technique vous permet de réduire les données requises pour l'affichage initial de l'arborescence aux seuls objets de niveau supérieur. . Si vous envisagez de créer un arborescence de plus de deux niveaux, plus vous ajoutez de niveaux à un arborescence, plus vous devez récupérer de données et plus de temps pour afficher cet affichage initial. Récupérer uniquement les nœuds dont vous avez besoin lorsque vous en avez besoin aide dans ces deux scénarios.

Mises en garde de version: j’ai testé ce code dans Visual Studio 2019 (16.3.1) fourni avec ASP.NET Core 3.0 (qui, à son tour, inclut la première version de production de Blazor). J'ai également utilisé le package Telerik.UI.for.Blazor NuGet, version 2.1.0.

Configuration de vos objets

La ​​première étape du processus consiste à définir l’objet que vous allez utiliser pour les noeuds de niveau supérieur de votre arborescence. Vous pouvez extraire ces objets de votre base de données mais, pour prendre en charge Telerik TreeView, chaque objet a besoin de propriétés supplémentaires qui n'existeront pas dans vos tables:

  • HasChildren: une propriété booléenne définie sur true pour indiquer qu'un nœud peut être expand (c.-à-d. qu'il a des nœuds «enfants»)
  • Expanded: propriété booléenne indiquant si le nœud est développé par l'utilisateur ou sous contrat

En outre, vos objets de niveau supérieur auront également besoin d'une propriété de collection contenant le les objets à afficher en tant que nœuds de second niveau dans l'arborescence (cette propriété peut déjà exister dans le modèle d'objet de vos données). Dans ce cas, vous avez besoin d'un objet de transfert de données (DTO) qui associe les données relatives à l'interface utilisateur aux données de votre base de données.

Cet exemple, CustomerDto, contient des données relatives à l'utilisateur de la base de données (CustId et FullName), propriété de collection contenant tous les objets d'adresse associés au client, plus les deux propriétés requises par l'interface utilisateur (HasChildren et Expanded):

 public class CustomerDto
{
   public int CustId {get; ensemble; }
   chaîne publique FullName {get; ensemble; }
   public IEnumerable 
Addresses {get; ensemble; }    public bool HasChildren {get; ensemble; }    public bool Expanded {get; ensemble; } }

J'ai décrit une approche LINQ-and-Entity-Framework permettant de créer un objet de ce type dans un article précédent .

Définition de la vue d'arborescence

Une fois ce processus en place, vous êtes prêt à Ajoutez une arborescence Telerik à votre composant. Le balisage comme suit ferait l'affaire:

  
    
    
 

Dans TreeView, vous devez définir l'attribut Data sur un champ ou une propriété de la section de code de votre composant qui contient la collection d'objets de niveau supérieur que vous souhaitez afficher (dans mon cas, il s'agit d'un champ appelé détient mes objets CustomerDto). Pour utiliser le code afin d'extraire et d'afficher les objets enfant / de second niveau, vous devez définir l'attribut OnExpand de TreeView sur le nom d'une méthode de la section de code de votre composant (j'ai appelé ma méthode GetAddresses).

Dans TreeViewBindings, vous aurez besoin d'au moins deux éléments TreeViewBinding. Le premier TreeViewBinding fait référence aux nœuds de niveau supérieur (CustomerDto, dans mon cas). TextField doit être défini sur une propriété de cet objet (j'ai utilisé FullName) et l'attribut ItemsField doit être défini sur la propriété qui contient les objets / enfants de second niveau (dans ce cas, la collection Adresses de mon objet CustomerDto). Si vous souhaitez faire plus que l’affichage d’une seule propriété dans un nœud TreeView, consultez mon post sur Création de modèles TreeView . Voici le premier TreeViewBinding:

  
    
        
    

Le second TreeViewBinding décrit ces ensembles de nœuds de second niveau / enfant. Dans mon cas, ce seront les objets adresse individuels de la propriété Adresses de CustomerDto. Pour cet exemple, je vais afficher la propriété City de l’objet Address dans chacun de ces nœuds de second niveau / enfants. Voici le balisage complet de la TreeView:

  
    
        
        
    

Si j'allais ajouter un troisième niveau (par exemple, les enfants de l'objet Address), je pourrais ajouter un attribut ItemsField au deuxième TreeViewBinding, ainsi qu'un troisième élément TreeViewBinding pour décrire ce troisième niveau.

Initialisation de TreeView.

Dans la section de code de mon composant, j'ai deux choses à faire. La première consiste à charger le champ auquel j'ai fait référence dans l'attribut ItemsField de mon TreeView qui contient les nœuds de niveau supérieur. Premièrement, je dois définir le champ qui contient ma collection d'objets CustomerDto:

 @code {
    privé IEnumerable ;

Ensuite, je dois charger ce champ avec les objets qui composent mes nœuds de niveau supérieur. Je veux le faire tôt dans le cycle de vie de mon composant, je mets donc ce code dans la méthode OnInitializedAsync du composant. Voici à quoi cela ressemblait:

 protégé async remplacer tâche OnInitializedAsync ()
    {
        custs = wait CustomerRepository.GetAllAsync ();
        attendez base.OnInitializedAsync ();
    }

Chargement des enfants

Il me faut maintenant écrire le code qui charge les nœuds de second niveau / enfants (les objets Adresse associés à chaque client). Je dois mettre ce code dans la méthode à laquelle j'ai fait référence dans l'attribut onExpand de TreeView (j'ai appelé cette méthode GetAddresses). Cette méthode recevra automatiquement un objet TreeViewExpandEventArgs, que je devrai intercepter pour l'utiliser dans ma méthode.
Voici à quoi ressemble la déclaration de cette méthode:

 tâche privée asynchrone GetAddresses (arguments TreeViewExpandEventArgs)
{

Fondamentalement, dans cette méthode, je vais utiliser les propriétés de TreeViewExpandEventArgs pour déterminer si le nœud est en cours d’expansion (si le nœud est réduit, je n’ai rien à faire). Ensuite, si le nœud est en cours d’expansion, je vais récupérer les objets enfants (les adresses du client, dans ce cas) et les insérer dans la propriété référencée dans la propriété ItemsField de l’élément TreeViewBinding (dans ce cas, le Adresses de l'objet CustomerDto). TreeView se chargera de les afficher correctement.

Il y a cependant deux rides que je dois traiter dans ce code. Tout d’abord, si cette propriété est déjà chargée, je n’ai plus besoin de récupérer cet objet (à moins, bien sûr, que je suppose que les données sous-jacentes sont si volatiles que j’ai toujours besoin de récupérer les données les plus récentes). Et, comme je l’ai dit plus tôt, si j’ai plusieurs niveaux pouvant être étendus, je dois également vérifier le type de nœud que je traite. Si, par exemple, un utilisateur peut également développer le nœud Adresse, je devrai inclure du code pour charger ses enfants.

En prenant tout cela en compte, ma méthode GetAddresses utilise d'abord la propriété Expanded de l'élément TreeViewExpandEventArgs pour afficher si le nœud est développé ou réduit (si Expanded est défini sur true, le nœud est développé). J'utilise ensuite la propriété Item de TreeViewExpandEventArgs (qui contient le nœud qui est développé) pour déterminer si je travaille avec un objet CustomerDto. Pour prendre en charge l’utilisation de cette méthode pour d’autres types d’objets, je vais définir cela comme un bloc de commutateur dans un bloc if:

 if (args.Expanded)
{
   commutateur (args.Item.GetType (). Name)
  {
     cas "CustomerDto":

Maintenant que je sais que le nœud est développé et que j'ai affaire à un objet CustomerDto, je transtyper ce nœud en une variable CustomerDto afin d'obtenir les propriétés de la classe CustomerDto:

 CustomerDto cust = args.Item en tant que CustomerDto;

L’étape suivante consiste à déterminer si j’ai déjà chargé la propriété Adresses (ce qui peut se produire si l’utilisateur développe un nœud précédemment développé). Si c'est le cas, je n'ai rien à faire et je peux simplement quitter ma méthode:

 if (cust.Addresses! = Null)
{
   revenir;
}

Maintenant que j'ai géré ce cas «spécial», je peux récupérer les objets Adresse du client et les insérer dans la propriété Adresses du CustomerDto en cours d’extension. Je dois également appeler la méthode StateHasChanged de Blazor pour que Blazor affiche le changement dans l’UI de TreeView. Si j'ai les bonnes classes en place, ce code peut être aussi simple que cela (j'ai également inclus l'instruction break requise par la structure de commutateur):

 cust.Addresses = wait AddressRepository.GetAddressesForCustomer (cust.CustId )
StateHasChanged ();
Pause;

J’ai probablement rendu ce son plus compliqué qu’il ne l’est. En tout, ma méthode GetAddresses ne contient que neuf lignes de code. Le voici dans son intégralité:

 tâche privée asynchrone GetAddresses (arguments TreeViewExpandEventArgs)
{
   if (args.Expanded)
   {
      commutateur (args.Item.GetType (). Name)
      {
         cas "CustomerDto":
                    CustomerDto cust = args.Item en tant que CustomerDto;
                    if (cust.Addresses! = null)
                    {
                        revenir;
                    }
                    cust.Addresses = wait AddressRepositoryAsync.GetAddressesForCustomer (cust.CustId);
                    Pause;
      }
      StateHasChanged ();
   }
}

En fait, je peux continuer à personnaliser l'apparence des objets Address attachés à mes nœuds TreeView. Rien ne m’empêche de créer un objet Address DTO avec une propriété Customer que je pourrais charger avec l’objet Customer associé, ce qui pourrait être utile lorsque l’utilisateur interagit avec les nœuds Address. La ligne de code supplémentaire avant l'instruction break dans mon instruction case ressemblerait à ceci:

 cust.Addresses.ToList (). ForEach (c => c.Customer = cust);

Et je peux continuer à étendre ce modèle. Pour prendre en charge, par exemple, un autre niveau de nœuds situés sous les nœuds d’adresses, il me suffirait d’étendre le bloc de commutation avec un autre bloc de cas (six lignes de code supplémentaires). Ce n'est pas mauvais pour un contrôle complet sur la manière dont votre arborescence ajoute des nœuds.

Essayez-le aujourd'hui

Pour en savoir plus sur l'interface utilisateur de Telerik pour les composants Blazor et sur ce qu'ils peuvent faire, consultez la page de démonstration de Blazor ou téléchargez un procès pour commencer immédiatement à vous développer.

Début du procès





Source link