2010-12-29 13 views
5

Voglio iniziare lo sviluppo di nuove applicazioni utilizzando PrismV4, MEF, Ribbon. Ma ora ho un problema. Come creare schede per Ribbon in modo dinamico? Ogni modulo dell'applicazione può creare la propria scheda in barra multifunzione. E ogni scheda può avere molti gruppi.Come creare le schede della barra multifunzione in modo dinamico?

Come può essere fatto? Dove devo posizionare le definizioni di ogni gruppo (quali controlli usare (pulsanti, caselle di testo, caselle combinate, ecc) e comandi bind e come?

Devo scrivere XAML da qualche parte nel Modulo, o tutto ciò che può essere fatto per codice? E ultima domanda, come comunicare a Ribbon (in Shell) per aggiungere queste schede a Ribbon? Devo usare EventAggregator per comunicare da Modulo a Shell? O?

risposta

2

Per le schede non contestuali, il mio approccio preferito per questo problema è caricare dinamicamente i componenti (tramite reflection per esempio) che includono XAML con binding a comandi e VM (o controller) che includono le implementazioni dei comandi ed eseguono i collegamenti dei comandi .

Per le schede contestuali, il mio approccio preferito consiste nell'includere un dizionario di mapping da Model a ViewModel, quindi attivare/disattivare le schede contestuali per nome, che sono state caricate utilizzando l'approccio sopra (e passano loro il contesto dati corretto - la vista modello).

Pseudo codice dovrebbe essere più o meno così (a seconda di ciò che i vostri quadri implementare e quello che hai da implementare da soli):

// Deserialize UI controllers from configuration files 
// Each controller should act as view-model for its UI elements 

// Register controllers with UI Manager 
foreach controller in config.UiControllers uiManager.AddController(controller); 


void UiManager.AddController(UiController controller) 
{ 
    // Load controller's tool windows 
    foreach toolWindow in contoller.toolWindows 
    { 
     toolWindow.LoadResources(); 
     toolWindow.DataContext = controller; 
     mainWindow.AddToolWindow(toolWindow, contoller.PreferedUiRegion); 
    } 

    // Load controller's toolbars 
    foreach toolBar in controller.ToolBars 
    { 
     toolBar.DataContext = controller; 
     mainWindow.AddToolBar(toolBar); 
    } 

    // Load controller's contextual toolbar groups 
    foreach group in controller.ContextualToolBarGroups 
    { 
     group.DataContext = controller; 
     mainWindow.AddContextualToolBarGroupr(group); 
    } 

    // Load view models for specific model types 
    foreach item in controller.ViewModelsDictionary 
    { 
     this.RegisterViewModelType(item.ModelType, item.ViewModelType, item.ViewType); 
    } 
} 


void UiManager.OnItemSelected(Object selectedItem) 
{ 
    var viewModelType = GetViewModelTypeFromDictionary(selectedItem); 
    var viewType = GetViewTypeFromDictionary(selectedItem) ?? typeof(ContentPresentor); 

    var viewModel = Reflect.CreateObject(viewModelType); 
    var view = Reflection.CreateObject(viewType); 

    viewModel.Model = selectItem; 
    view.DataContext = viewModel; 

    // Enable activation of contextual tab group on activate of view (if user clicks on it) 
    view.OnActivatedCommandParameter = viewModel.ContextualTabGroupName; 

    // This command should ask mainWindow to find contextual tab group, by name, and activate it 
    view.OnActivatedCommand = ModelActivatedCommand; 

    mainWindow.DocumentArea.Content = view; 
} 
+0

Grazie per la risposta. Puoi fornire un piccolo esempio di codice per questo? – Lari13

+0

Il codice varia a seconda dei framework che si sta utilizzando, tuttavia potrei aggiungere un esempio di pseudo codice. –

+0

Uso PrismV4 con MEF. Penso che il codice pesudo sia ok :) Grazie – Lari13

2

Penso che dovrai usare Adattatore di regione (per il trattamento di controlli standard non supportati (non supportati come regioni)

http://msdn.microsoft.com/en-us/library/dd458901.aspx

Sopra il collegamento può essere un buon punto di partenza. Quindi puoi registrare le tue schede come viste (non sono sicuro perché non ho usato la barra multifunzione).

Altrimenti è possibile esporre un servizio IRibbonService che moduli diversi includono nel proprio costruttore e quindi è possibile chiamare metodi come AddTab/AddGroup.

+0

Grazie. Potrebbe essere la risposta all'ultima domanda sulla comunicazione tra modulo e "MainModule". Controllerò. Cosa sta per creare questo RibbonTab in ogni modulo? Come è il modo giusto per implementarlo? – Lari13

+0

La soluzione con 'IRibbonService' sembra essere molto carina. Grazie! – Lari13

1

creare una vista per scheda della barra multifunzione: vista:

<!-- See code-behind for implementation of IRegionMemberLifetime interface. This interface 
causes the RibbonTab to be unloaded from the Ribbon when we switch views. --> 

<!--<ribbon:RibbonGroup Header="Group B1"> 
    <ribbon:RibbonButton LargeImageSource="Images\LargeIcon.png" Label="Button B1" /> 
    <ribbon:RibbonButton SmallImageSource="Images\SmallIcon.png" Label="Button B2" /> 
    <ribbon:RibbonButton SmallImageSource="Images\SmallIcon.png" Label="Button B3" /> 
    <ribbon:RibbonButton SmallImageSource="Images\SmallIcon.png" Label="Button B4" /> 
</ribbon:RibbonGroup>--> 

cs:

using Microsoft.Practices.Prism.Regions; 
//using Microsoft.Windows.Controls.Ribbon; 

namespace Prism4Demo.ModuleB.Views 
{ 
    /// <summary> 
    /// Interaction logic for ModuleBRibbonTab.xaml 
    /// </summary> 
    public partial class ModuleBRibbonTab : IRegionMemberLifetime 
    { 
     #region Constructor 

     public ModuleBRibbonTab() 
     { 
      InitializeComponent(); 
     } 

     #endregion 

     #region IRegionMemberLifetime Members 

     public bool KeepAlive 
     { 
      get { return false; } 
     } 

     #endregion 
    } 
} 

Classe Modulo:

public class ModuleC : IModule 
    { 
     #region IModule Members 

     /// <summary> 
     /// Initializes the module. 
     /// </summary> 
     public void Initialize() 
     { 
      /* We register always-available controls with the Prism Region Manager, and on-demand 
      * controls with the DI container. On-demand controls will be loaded when we invoke 
      * IRegionManager.RequestNavigate() to load the controls. */ 

      // Register task button with Prism Region 
      var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>(); 
      regionManager.RegisterViewWithRegion("TaskButtonRegion", typeof(ModuleBTaskButton)); 

      /* View objects have to be registered with Unity using the overload shown below. By 
      * default, Unity resolves view objects as type System.Object, which this overload 
      * maps to the correct view type. See "Developer's Guide to Microsoft Prism" (Ver 4), 
      * p. 120. */ 

      // Register other view objects with DI Container (Unity) 
      var container = ServiceLocator.Current.GetInstance<IUnityContainer>(); 
      container.RegisterType<Object, ModuleBRibbonTab>("ModuleBRibbonTab"); 
      container.RegisterType<Object, ModuleBNavigator>("ModuleBNavigator"); 
      container.RegisterType<Object, ModuleBWorkspace>("ModuleBWorkspace"); 
     } 
Problemi correlati