2010-12-29 22 views
5

Quiero comenzar el desarrollo de nuevas aplicaciones usando PrismV4, MEF, Ribbon. Pero ahora, tengo un problema. ¿Cómo crear pestañas para Ribbon dinámicamente? Cada módulo en la aplicación podría crear una pestaña propia en la cinta de opciones. Y cada pestaña puede tener muchos grupos.Cómo crear las pestañas de la cinta de forma dinámica?

¿Cómo se puede hacer? ¿Dónde tengo que poner las definiciones de cada grupo (lo que controla a utilizar (botones, cuadros de texto, cuadros combinados, etc.) y los enlaces de comando y cómo?

¿Es necesario escribir XAML en algún lugar en el Módulo, o todo lo que se puede hacer ¿Por código? Y última pregunta, ¿cómo notificar a Ribbon (en Shell) para agregar estas pestañas a Ribbon? ¿Usaré EventAggregator para comunicarme de Module a Shell? O?

Respuesta

2

Para pestañas no contextuales, mi enfoque favorito para este problema es cargar dinámicamente los componentes (a través de la reflexión por ejemplo) que incluyen XAML vinculante a comandos y máquinas virtuales (o controladores) que incluyen las implementaciones de comandos y realizar los comandos de enlaces .

Para las pestañas contextuales, mi enfoque favorito es incluir un diccionario de mapeos Model to ViewModel, luego activar/desactivar pestañas contextuales por nombre, que se cargan utilizando el enfoque anterior (y pasarles el contexto de datos correcto - la vista modelo).

Pseudo código debería ser más o menos así (dependiendo de lo que sus marcos de implementar y lo que tiene que implementar uno mismo):

// 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

Gracias por responder. ¿Puedes proporcionar un pequeño ejemplo de código para ello? – Lari13

+0

El código varía dependiendo de los marcos que está usando, aunque podría agregar un ejemplo de pseudo código. –

+0

Uso PrismV4 con MEF. Creo que el código Pesudo también está bien :) Gracias – Lari13

2

Creo que tendrá que usar el adaptador de región (para el tratamiento no estándar (no soportado fuera de la caja de controles como regiones)

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

El enlace de arriba puede ser un buen punto de partida. Entonces puede registrar sus pestañas como vistas (no estoy seguro porque no he usado cinta).

De lo contrario, puede exponer un servicio IRibbonService que diferentes módulos toman en su constructor y luego puede llamar a métodos como AddTab/AddGroup.

+0

Gracias. Podría ser la respuesta a la última pregunta sobre commincation entre Module y "MainModule". Lo revisaré. ¿Qué está por crear este RibbonTab en cada Módulo? ¿Cómo es la forma correcta de implementarlo? – Lari13

+0

La solución con 'IRibbonService' parece ser muy buena. ¡Gracias! – Lari13

1

crear una vista de ficha de la cinta: 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 
    } 
} 

clase Módulo:

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"); 
     } 
Cuestiones relacionadas