Azioni del controllo

Ad ogni controllo possono essere aggiunte una o più azioni. Le azioni sono visualizzate nell'apposito menù a destra del controllo:
 
Actions example
 
Questi sono di tipi di azione disponibili:
 
  • UpdateData: azione di aggiornamento dei dati del controllo
  • SetNavigation: azione di navigazione a un'altra sezione o item
  • SetLocalAction: azione per l'esecuzione di codice personalizzato lato server
  • SetRemoteAction: azione per l'esecuzione di codice personalizzato lato client
 
La classe ControlBase mette a disposizione alcuni metodi per aggiungere rapidamente una nuova azione alla lista Actions del controllo.
Questo è un esempio di implementazioni di questi metodi:
 
        public void AddActionSetNavigation(string title, Action.Step currentStep, List<Action.Step> newSteps)
        {
            this.Actions.Add(new Action()
            {
                Mode = ActionMode.SetNavigation,
                Title = title,
                CurrentStep = currentStep,
                NewSteps = newSteps != null ? newSteps : new List<Action.Step>(),
                Type = ActionType.Navigation
            });
        }
 
Azione UpdateData
Il metodo aggiunge un'azione di aggiornamento dei dati nel controllo in modo da non dover ricaricare la pagine se la sorgente dati è stata modificata dopo l'apertura del form. Il codice seguente aggiunge l'opzione di aggiornamento per il controllo predefinito CheckBoxList.
 
using System;
using System.Threading.Tasks;

namespace DataWeb.Data.Controls
{
    public class CheckBoxList : ControlBase
    {
        public CheckBoxList(Form form, IServiceProvider serviceProvider) : base(form, serviceProvider)
        {
        }

        public override Task InitAsync()
        {
            AddActionUpdateData();

            return Task.CompletedTask;
        }
    }
}
 
Va segnalato che tutti i controlli predefiniti che gestiscono liste di valori (CheckBoxList, ListBox, RadioButtonList, DropDownList, ecc.) hanno già impostata questa azione.
 
Azione SetNavigation
Il metodo aggiunge un'azione che permette all'utente di aprire una sezione o un item rapidamente. Ad esempio, dato un DropDownList con un elenco di categorie, si vuole permettere all'utente di aggiungerne una nuova, modificare quella selezionata o aprire la sezione dedicata.
DataWeb salverà automaticamente i dati dell'item prima di impostare la navigazione. La navigazione viene aggiunta a quella esistente ovvero quando l'utente chiude la categoria viene riportato all'item di partenza rendendo l'esperienza più piacevole.
 
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using DataWeb.Structure;
using DataWeb.Identity;
using DataWeb.Data;
using DataWeb.Data.Controls;
using DataWeb.WebApp.Infrastructure;
using Microsoft.Extensions.Localization;

namespace DataWeb.WebApp.DataWeb.Data.Controls
{
    public class Product_CategoryName :  DropDownList
    {
        private readonly CategoryRepository categoryRepository;
        private readonly IStringLocalizer localizer;

        public Product_CategoryName(Form form, IServiceProvider serviceProvider) : base(form, serviceProvider)
        {
            categoryRepository = serviceProvider.GetService<CategoryRepository>();
            localizer = serviceProvider.GetService<IStringLocalizer>();
        }

        public override async Task InitAsync()
        {
            await base.InitAsync();

            AddActionSetNavigation(localizer["DataWeb.Form.ControlAction_EditSelected"], new List<Action.Step>()
            {
                new Action.Step{ IdMaster = StructureDefinition.RootIdMaster, SectionName = AppStructureDefinition.SectionDemoCategories, IsHidden = true },
                new Action.Step{ IdMaster = "{ {IdMaster} }", SectionName = AppStructureDefinition.SectionDemoCategoryData }
            });

            AddActionSetNavigation(localizer["DataWeb.Form.ControlAction_New"], new List<Action.Step>()
            {
                new Action.Step{ IdMaster = StructureDefinition.RootIdMaster, SectionName = AppStructureDefinition.SectionDemoCategories, IsHidden = true },
                new Action.Step{ IdMaster = StructureDefinition.VoidIdMaster, SectionName = AppStructureDefinition.SectionDemoCategoryData }
            });

            AddActionSetNavigation(localizer["DataWeb.Form.ControlAction_OpenSection"], new List<Action.Step>()
            {
                new Action.Step{ IdMaster = StructureDefinition.RootIdMaster, SectionName = AppStructureDefinition.SectionDemoCategories }
            });
        }
    }
}
 
Al metodo deve essere fornito il titolo dell'azione (nell'esempio localizzato con Localizer) e i nuovi step di navigazione. Il parametro opzionale currentStep permette di spostarsi iin una sezione adiacente a quella attuale.
 
Azione SetLocalAction
Il metodo aggiunge un'azione che permette all'utente di eseguire del codice client posizionato nel componente Vue.js personalizzato.
Ad esempio nel controllo User_AccountNewsletter troviamo l'aggiunta dell'azione locale (client) Edit:
 
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DataWeb.Identity;
using DataWeb.Structure;
using DataWeb.Validation;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;

namespace DataWeb.Data.Controls
{
    public class User_AccountNewsletter : ControlBase
    {
        private readonly IStringLocalizer localizer;

        public User_AccountNewsletter(Form form, IServiceProvider serviceProvider) : base(form, serviceProvider)
        {
            localizer = serviceProvider.GetService<IStringLocalizer>();
        }

        public override Task InitAsync()
        {
            AddActionSetLocalAction(localizer["DataWeb.Form.AccountNewsletter_Edit"], "Edit", ActionType.Edit);

            return Task.CompletedTask;
        }

        public override Task<List<ValidationError>>ValidateAsync(object value, List<Form.ProvidedValue> providedValues, Dictionary<string, object> sectionData, IUser user, string itemId = null, NavigationContext navigationContext = null)
        {
            var errors = new List<ValidationError>();

            return Task.FromResult(errors);
        }

        public override Task<bool> IsUpdateDataAsync(object value, List<Form.ProvidedValue> providedValues, Dictionary<string, object> sectionData, IUser user, string itemId = null, NavigationContext navigationContext = null)
        {
            return Task.FromResult(false);
        }
    }
}
 
E nel codice del componente Vue.js intecettiamo la selezione dell'azione Edit:
 
    public startLocalAction(action: any) {
        switch (action.name) {
            case "Edit":
                this.edit();
                break;
        }
    }
 
Azione SetRemoteAction
Il metodo aggiunge un'azione che verrà eseguita lato server, da un metodo C# dedicato.
Qui ad esempio stiamo impostando un'azione di notifica tramite email:
 
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using DataWeb.Structure;
using DataWeb.Identity;
using DataWeb.Data;
using DataWeb.Data.Controls;
using DataWeb.WebApp.Infrastructure;
using Microsoft.Extensions.Localization;

namespace MyApp.DataWeb.Data.Controls
{
    public class Product_ActionListAreaName :  ActionList
    {
        private readonly IStringLocalizer localizer;
        private readonly ProductStore productStore;

        public Product_ActionListAreaName(Form form, IServiceProvider serviceProvider) : base(form, serviceProvider)
        {
            localizer = serviceProvider.GetService<IStringLocalizer>();
            productStore = serviceProvider.GetService<ProductStore>();
        }

        public override async Task InitAsync()
        {
            await base.InitAsync();

            AddActionSetRemoteAction("Notify status", "NotifyStatus", ActionType.Notification);
        }

        public override async Task<ActionResult> SetCustomActionAsync(Action action, IUser user, string itemId = null, NavigationContext navigationContext = null)
        {
            var result = await base.SetCustomActionAsync(action, user, itemId, navigationContext);
            if (!result.IsValid)
            {
                return result;
            }

            switch (action.Name)
            {
                case "NotifyStatus":
                    result = await NotifyStatus(itemId);
                    break;
            }

            return result;
        }

        public async Task<ActionResult> NotifyStatus(string itemId = null)
        {
            bool isSuccess = await productStore.SendEmailAsync(itemId);

            return new ActionResult { IsValid = isSuccess };
        }
    }
}
 
Va segnalato che l'esecuzione di un'azione remota aggiorna sempre il form ricaricando i dati. Inoltre prima di eseguire l'azione, i dati vengono validati e salvati.