Как динамически создавать вкладки ленты? - PullRequest
6 голосов
/ 29 декабря 2010

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

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

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

Ответы [ 3 ]

3 голосов
/ 29 декабря 2010

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

Для контекстных вкладок мой любимый подход состоит в том, чтобы включить словарь сопоставлений модели с 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;
}
3 голосов
/ 29 декабря 2010

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

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

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

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

1 голос
/ 27 апреля 2011

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

<!-- 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");
        }
...