Come illustrato in Deploy di una custom action nella ribbon è possibile aggiungere dei bottoni sulla ribbon di SharePoint 2010 legati ad uno specifico content type.
L'abilitazione o meno del bottone è controllata tramite l'attributo EnabledScript della sezione CommandUIHandlers.
Nel caso si volesse abilitare il bottone solo quando si seleziona un solo item la cosa è semplice:
XML
<CommandUIHandler
       Command="Sgart_Cmd_Edit"
       CommandAction="javascript:..."
       EnabledScript="javascript:
         function enableSgartCmdEdit()
         {
           var items = SP.ListOperation.Selection.getSelectedItems();
           return (items.length == 1);
         }
         enableSgartCmdEdit();"
       />
    </CommandUIHandlers>
conto gli item selezionati e restituisco true se ho un solo elemento.

Se però nella lista ho più content type e voglio abilitare la visualizzazione sull'item solo su uno specifico content type... la cosa si complica.
Infatti nella variabile items non ho niente che mi dice quale content type è associato ad ogni item. questo significa che devo fare una chiamata asincrona, tramite il modello ad oggetti JavaScript, a SharePoint per recuperare il content type associato all'item.

Qui un esempio:
XML
<CustomAction Id="SgartEditRibbon"
  RegistrationType="ContentType"
  RegistrationId="0x01012BB0B1C886E8415AB34C2B11C7B3CBE6"
  Location="CommandUI.Ribbon.ListView"
  Title="Edit Questions">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.ListItem.Actions.Controls._children">
          <Button Id="Ribbon.Items.Actions.EditQuestion"
              Sequence="100"
              Command="Sgart_Cmd_Edit"
              Image32by32="~site/_layouts/images/CRIT_32.GIF"
              Image16by16="~site/_layouts/images/CRIT_16.GIF"
              LabelText="Edit Questions"
              TemplateAlias="o1" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
         Command="Sgart_Cmd_Edit"
         CommandAction="javascript:location.href='{SiteUrl}/_Layouts/sgart/Edit.aspx?SgartID={SelectedItemId}&Source={Source}'"
         EnabledScript="javascript:  
         function enableSgartCmdEdit()
         {
           if(window.enableSgartCmd_EditId === undefined){
             window.enableSgartCmd_EditId = [];
           }
           var items = SP.ListOperation.Selection.getSelectedItems();
           if(items.length == 1) {
            var id = items[0].id;
            if(enableSgartCmd_EditId[id] === undefined){ 
              enableSgartCmdEdit_GetCT(id); 
            }else{
              return enableSgartCmd_EditId[id];
            }
           }else{
            return false;
           }
         }
       
         function enableSgartCmdEdit_GetCT(id){
          var context = SP.ClientContext.get_current();
          var web = context.get_web();
          var listId = SP.ListOperation.Selection.getSelectedList();
          var list = web.get_lists().getById(listId)
          var item = list.getItemById(id);
          
          context.load(item, 'ContentTypeId');  

          context.executeQueryAsync(function(sender, args) {
            var correctContentTypeId = ['0x01012BB0B1C886E8415AB34C2B11C7B3CBE6', '0x0100E06DF65DF9564DDB9AA297084E500608'];
            var contentTypeId = item.get_item('ContentTypeId').toString();
      
            if (contentTypeId.indexOf(correctContentTypeId[0]) == 0 
              //|| contentTypeId.indexOf(correctContentTypeId[1]) == 0
              ) 
            {
              enableSgartCmd_EditId[id] = true;
            } else {
              enableSgartCmd_EditId[id] = false;
            }
            RefreshCommandUI();
           }, function(sender, args) {
            alert(args);
           }
          );
        }
         enableSgartCmdEdit();
         "
      />
    </CommandUIHandlers>
  </CommandUIExtension>
</CustomAction>
Come funziona?
Prima di tutto mi assicuro di avere una array window.enableSgartCmd_EditId globale per mantenere lo stato tra le chiamate asincrone e il refresh della ribbon.
Poi, se ho un solo elemento selezionato, faccio una chiamata asincrona (enableSgartCmdEdit_GetCT) per farmi ritornare il content type associato all'item corrente. Essendo la chiamata asincrona l'unica cosa che posso fare, non avendo ancora il content type, è restituire false e lasciare il pulsante disabilitato.
Nella funzione enableSgartCmdEdit_GetCT costruisco la chiamata asincrona, quando arriva la riposta controllo se il content type è quello che volevo e imposto la variabile globale (enableSgartCmd_EditId[id]) a true. A questo punto l'unico modo che ho per aggiornare la ribbon è invocare la chiamata RefreshCommandUI che esegue tutte le funzioni definite nell'attributo EnabledScript di tutti i bottoni della ribbon.
A questo punto lo script viene eseguito di nuovo, ma trovando un valore nell'array enableSgartCmd_EditId, indicizzato tramite l'id dell'item, non esegue la chiamata asincrona, ma resituisce il valore true o false memorizzato immediatamente.

Ovviamente ci sarà un piccolo ritardo nell'abilitazione del pulsante la prima volta che viene selezionato.
Potrebbe interessarti anche: