2010-12-29 2 views
5

Я хочу начать разработку нового приложения с помощью PrismV4, MEF, Ribbon. Но теперь у меня есть проблема. Как динамически создавать вкладки для ленты? Каждый модуль в приложении может создать собственную вкладку в ленте. И каждая вкладка может иметь много групп.Как создать вкладки Ribbon динамически?

Как это сделать? Где мне нужно размещать определения каждой группы (какие элементы управления использовать (кнопки, текстовые поля, выпадающие списки и т. Д.) И командные привязки и как?

Нужно ли писать XAML где-нибудь в модуле или все это можно сделать по коду? И последний вопрос, как уведомить ленту (в оболочке), чтобы добавить эти вкладки в ленту? Должен ли я использовать EventAggregator для связи из модуля в оболочку? Или?

ответ

2

Для неконтекстных вкладок моим любимым подходом к этой проблеме является динамическая загрузка компонентов (например, через отражение), которые включают в себя XAML с привязкой к командам и виртуальным машинам (или контроллерам), которые включают в себя реализации команд и выполняют эти командные привязки ,

Для контекстных вкладок мой любимый подход состоит в том, чтобы включить словарь для сопоставлений Model to ViewModel, а затем активировать/деактивировать контекстные вкладки по имени, которые были загружены с использованием вышеуказанного подхода (и передать им правильный контекст данных - представление модель).

Псевдо код должен быть больше или меньше, как это (в зависимости от того, что ваши рамки осуществления и то, что вы должны реализовать себя):

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

Спасибо за ответ. Можете ли вы представить для него небольшой пример кода? – Lari13

+0

Код зависит от используемых вами фреймворков, однако я мог бы добавить пример псевдокода. –

+0

Я использую PrismV4 с MEF. Я думаю, что код pesudo тоже в порядке :) Спасибо – Lari13

2

Думаю, вам придется использовать адаптер региона (для обработки нестандартных (не поддерживаемых готовых элементов управления в качестве регионов)

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

Выше ссылка может быть хорошей отправной точкой. Тогда вы можете зарегистрировать свои вкладки в качестве просмотров, возможно (я не уверен, потому что я не использовал ленту).

В противном случае вы можете предоставить сервис IRibbonService, который использует разные модули в своем конструкторе, и вы можете затем вызвать методы, такие как AddTab/AddGroup.

+0

Спасибо. Это может быть ответ на последний вопрос о коммиксации между модулем и «MainModule». Я проверю его. Что собирается создать этот RibbonTab в каждом модуле? Как правильно его реализовать? – Lari13

+0

Решение с «IRibbonService» кажется очень приятным. Благодаря! – Lari13

1

Создать представление для вкладки ленты: вид:

<!-- 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 
    } 
} 

класс модуля:

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"); 
     } 
Смежные вопросы