IRibbonComponentProviders
Note
IRibbonComponentProviders provide component that can be placed on the Ribbon in MicroStation

IRibbonComponentProviders

Managed applications can provide their own components for the Ribbon by implementing the IRibbonComponentProvider interface and registering it with the RibbonComponentManager. This interface allows application provided to properly work with standard ribbon features such as ribbon search, popup groups, and Hidden Tool resources. The following shows an example of registering a provider:

RibbonComponentManager.Manager.RegisterRibbonComponentProvider (new RibbonComponentProvider ());

A RibbonComponent has three basic requirements. It must supply/register a definition of itself. It must create a viewmodel that will serve as a data context for actual WPF control. It must create the WPF control that will be inserted into the ribbon.

The definition must supply a name and that name must be unique for the component type. For example two button definitions should not have the same name. A list of the primary component types are shown below.

Component Type Definition Type ViewModel Type Control Type
Tab RibbonTabDefinition RibbonTabViewModel RadRibbonTab
Group RibbonGroupDefinition RibbonGroupViewModel RadRibbonGroup
Panel RibbonGroupPanelDefinition RibbonGroupPanelViewModel StackPanel,RadCollapsiblePanel, or RadOrderedWrapPanel
ButtonGroup RibbonButtonGroupDefinition RibbonButtonGroupViewModel RadButtonGroup
Button RibbonButtonDefinition RibbonButtonViewModel RadRibbonButton
DropDownButton RibbonDropDownButtonDefinition RibbonDropDownButtonViewModel RadRibbonDropDownButton
SplitButton RibbonSplitButtonDefinition RibbonSplitButtonViewModel RadRibbonSplitButton
ToggleButton RibbonToggleButtonDefinition RibbonToggleButtonViewModel RadRibbonToggleButton
RadioButton RibbonRadioButtonDefinition RibbonRadioButtonViewModel RadRibbonRadioButton
ComboBox RibbonComboBoxDefinition RibbonComboBoxViewModel RadRibbonComboBox
Gallery RibbonGalleryDefinition RibbonGalleryViewModel RadRibbonGallery

The names of the definitions are used to configure the presentation of the Ribbon. To see example configurations look at the XML files in MstnPlatform .

The Bentley.MstnPlatformNET.Ribbon.IRibbonComponentProvider interface definition is shown below:

public interface IRibbonComponentProvider
{
String ProviderKey {get;}
IList<RibbonTabCollectionDefinition> RegisterTabCollectionDefinitions ();
IList<ContextualTabSetDefinition> RegisterContextualTabSetDefinitions ();
IList<QuickAccessCollectionDefinition> RegisterQuickAccessCollectionDefinitions ();
IList<RibbonButtonGroupDefinition> RegisterButtonGroupDefinitions ();
IList<RibbonButtonDefinition> RegisterButtonDefinitions ();
IList<RibbonDropDownButtonDefinition> RegisterDropDownButtonDefinitions ();
IList<RibbonSplitButtonDefinition> RegisterSplitButtonDefinitions ();
IList<RibbonToggleButtonDefinition> RegisterToggleButtonDefinitions ();
IList<RibbonRadioButtonDefinition> RegisterRadioButtonDefinitions ();
IList<RibbonComboBoxDefinition> RegisterComboBoxDefinitions ();
IList<RibbonTabDefinition> RegisterTabDefinitions ();
IList<RibbonMenuItemCollectionDefinition> RegisterMenuItemCollectionDefinitions ();
IList<RibbonGroupPanelDefinition> RegisterGroupPanelDefinitions ();
IList<RibbonGroupDefinition> RegisterGroupDefinitions ();
IList<RibbonGalleryDefinition> RegisterGalleryDefinitions ();
IList<WorkflowDefinition> RegisterWorkflowDefinitions ();
IList<RibbonDropDownPanelDefinition> RegisterDropDownPanelDefinitions ();
IList<BackstageItemDefinition> RegisterBackstageItemDefinitions ();
ContextualTabSetViewModel CreateContextualTabSetViewModelFromDefinition (ContextualTabSetDefinition def);
TabCollectionViewModel CreateTabCollectionViewModelFromDefinition (RibbonTabCollectionDefinition def);
QuickAccessToolbarViewModel CreateQuickAccessCollectioniewModelFromDefinition (QuickAccessCollectionDefinition def);
IRibbonItemViewModel CreateButtonGroupViewModelFromDefinition (RibbonButtonGroupDefinition def);
IRibbonItemViewModel CreateButtonViewModelFromDefinition (RibbonButtonDefinition def);
IRibbonItemViewModel CreateDropDownButtonViewModelFromDefinition (RibbonDropDownButtonDefinition def);
IRibbonItemViewModel CreateSplitButtonViewModelFromDefinition (RibbonSplitButtonDefinition def);
IRibbonItemViewModel CreateToggleButtonViewModelFromDefinition (RibbonToggleButtonDefinition def);
IRibbonItemViewModel CreateRadioButtonViewModelFromDefinition (RibbonRadioButtonDefinition def);
IRibbonItemViewModel CreateComboBoxViewModelFromDefinition (RibbonComboBoxDefinition def);
IRibbonItemViewModel CreateTabViewModelFromDefinition (RibbonTabDefinition def);
RibbonMenuItemCollectionViewModel CreateMenuItemCollectionViewModelFromDefinition (RibbonMenuItemCollectionDefinition def);
IRibbonItemViewModel CreateGroupPanelViewModelFromDefinition (RibbonGroupPanelDefinition def);
IRibbonItemViewModel CreateGroupViewModelFromDefinition (RibbonGroupDefinition def);
IRibbonItemViewModel CreateGalleryViewModelFromDefinition (RibbonGalleryDefinition def);
IRibbonItemViewModel CreateBackstageItemViewModelFromDefinition (BackstageItemDefinition def, ViewModelContext context);
RadButtonGroup CreateButtonGroupFromViewModel (IRibbonItemViewModel item);
RadRibbonButton CreateButtonFromViewModel (IRibbonItemViewModel item);
RadDropDownButton CreateDropDownButtonFromViewModel (IRibbonItemViewModel item);
RadRibbonSplitButton CreateSplitButtonFromViewModel (IRibbonItemViewModel item);
RadRibbonToggleButton CreateToggleButtonFromViewModel (IRibbonItemViewModel item);
RadRibbonRadioButton CreateRadioButtonFromViewModel (IRibbonItemViewModel item);
RadRibbonComboBox CreateComboBoxFromViewModel (IRibbonItemViewModel item);
RadRibbonTab CreateTabFromViewModel (IRibbonItemViewModel item);
Object CreatePanelFromViewModel (IRibbonItemViewModel item);
RadRibbonGroup CreateGroupFromViewModel (IRibbonItemViewModel item);
RadRibbonGallery CreateGalleryFromViewModel (IRibbonItemViewModel item);
RadRibbonBackstageItem CreateBackstageItemFromViewModel (IRibbonItemViewModel itemVm);
}

The class Bentley.MstnPlatformNET.Ribbon.BaseRibbonComponentProvider is provided to allow users to easily implement RibbonComponentProviders which only provide a subset of possible component types. For an example implementation of an IRibbonComponentProvider, see the file MstnPlatform .cs which provides Tab, DropDownButton, and ComboBox components current seen in the Ribbon.

Specifying Ribbon Component Providers

The variable MS_RIBBONCOMPONENTPROVIDERS is used to specify ribbon component providers. The RibbonView application will load the specified provider dll and create the class that is specified by the InstanceOnLoad attribute.

Example - Setting up a component provider

Addin Name:
MyComponentProvider.dll
cfg setting:
MS_RIBBONCOMPONENTPROVIDERS < MyComponentProvider
[Bentley.MstnPlatformNET.Ribbon.InstanceOnLoad]
public class MyComponentProvider : Bentley.MstnPlatformNET.Ribbon.BaseRibbonComponentProvider
{
/*------------------------------------------------------------------------------------**/
/*--------------+---------------+---------------+---------------+---------------+------*/
public MyComponentProvider
(
)
{
RibbonComponentManager.Manager.RegisterRibbonComponentProvider (this)
}
/*------------------------------------------------------------------------------------**/
/*--------------+---------------+---------------+---------------+---------------+------*/
public override string ProviderKey
{
get {return "MyComponentProvider.RibbonComponentProvider"; }
}
/*------------------------------------------------------------------------------------**/
/*--------------+---------------+---------------+---------------+---------------+------*/
~ MyComponentProvider() // destructor
{
RibbonComponentManager.Manager.UnRegisterRibbonComponentProvider (this.Name)
}
/*------------------------------------------------------------------------------------**/
/*--------------+---------------+---------------+---------------+---------------+------*/
public override IList<RibbonDropDownButtonDefinition> RegisterDropDownButtonDefinitions ()
{
...
}
/*------------------------------------------------------------------------------------**/
/*--------------+---------------+---------------+---------------+---------------+------*/
public override IRibbonItemViewModel CreateDropDownButtonViewModelFromDefinition (RibbonDropDownButtonDefinition def)
{
switch (def.Name)
{
case "MyDropDownItem":
{
MyIRibbonItemVeiwModelBasedViewModel vm = new ....
// set any specific property overrides from definition, like AccessText
RibbonViewModelHelper.CopyPropertiesFromDefinition (vm, def);
return vm;
}
}
return null;
}
/*------------------------------------------------------------------------------------**/
/*--------------+---------------+---------------+---------------+---------------+------*/
public override RadDropDownButton CreateDropDownButtonFromViewModel (IRibbonItemViewModel itemVm)
{
switch (def.Name)
{
case "MyDropDownItem":
{
MyIRibbonItemVeiwModelBasedViewModel myVm = itemVm as MyIRibbonItemVeiwModelBasedViewModel;
RadDropDownButton button = new MyDropDownButton (myVm); // button.DataContext should be set to your ViewModel (myVm)
// set any specific overrides from definition, like AccessText and ToolTips
RibbonComponentHelper.SetRadDropDownButtonPropertiesFromVM(button, itemVm);
return button;
}
}
return null;
}

Setting style to make Sure Your xaml supplied Tab, Groups and Buttons display

Step 1. Ensure your addin is subclassed from WpfAddin and make sure to define a ThemStyle attribute that specifies where the style resources are located.

[Bentley.MstnPlatformNET.AddInAttribute(MdlTaskID = "TableUI")]
[ThemeStyle ("Bentley.TableUI", "Themes/Common.xaml")]
public classTableUIApp : WpfAddIn
{

Step 2. Define your styles in Common.xaml, below is an example.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"xmlns:local="clr-namespace:Bentley.MstnPlatformNET.TableUI.Views">
<Style BasedOn="{StaticResource RadRibbonButtonStyle}" TargetType="{x:Type local:DistributeColumnsButton}"/>
<Style BasedOn="{StaticResource RadRibbonButtonStyle}" TargetType="{x:Type local:DistributeRowsButton}"/>
<Style BasedOn="{StaticResource RadRibbonGroupStyle}" TargetType="{x:Type local:TableSymbologyGroup}"/>
<Style BasedOn="{StaticResource RadRibbonGroupStyle}" TargetType="{x:Type local:TableOptionsGroup}"/>
<Style BasedOn="{StaticResource RadRibbonDropDownButtonStyle}" TargetType="{x:Type local:ShadingDropDownButton}"/>
<Style BasedOn="{StaticResource BentleyRibbonDropDownButtonStyle}" TargetType="{x:Type local:TableColorDropDownButton}" >
<Setter Property="DropDownHeight"Value="450" /><Setter Property="DropDownWidth"Value="500" />
<Style BasedOn="{StaticResource BentleyRibbonDropDownButtonStyle}" TargetType="{x:Type local:TableLineStyleDropDownButton}" >
<Setter Property="DropDownHeight"Value="500" /><Setter Property="DropDownWidth"Value="180" />
<Style BasedOn="{StaticResource BentleyRibbonDropDownButtonStyle}" TargetType="{x:Type local:TableLineWeightDropDownButton}" >
<Setter Property="DropDownHeight"Value="400" /><Setter Property="DropDownWidth"Value="170" />
<Style BasedOn="{StaticResource RadRibbonSplitButtonStyle}" TargetType="{x:Type local:TableBordersSplitButton}"/>
<Style BasedOn="{StaticResource RadRibbonGroupStyle}" TargetType="{x:Type local:CellSizeGroup}"/>
<Style BasedOn="{StaticResource RadRibbonGroupStyle}" TargetType="{x:Type local:TableSizeGroup}"/>
</ResourceDictionary>

Supporting RightClick HiddenTool Processing (and RibbonSearch support)

If you want the Ribbon to see your components when it collects up a list of items to display the Show/Hide right click menu, the ViewModel set as the DataContext of your component must implement the ISupportsHidingViaUserPrefs interface and provide a non-null UniqueOccurrenceName, UniqueOccurrenceLabel, ParentOccurence, and ItemType. This Interface includes the interface ISupportUniqueOccurrence which is used to add entries into the Ribbon Search box. So if you implement ISupportsHidingViaUserPrefs your component is compatible with both features. These interfaces are also implemented in IRibbonItemViewModel. Since the RibbonComponentManager uses IRibbonItemViewModel, your viewmodels should automatically work with both features. Note, that currently only components that implement ISupportsMstnRelayCommand will be shown in Ribbon Search.

If your component provider is providing a RadRibbonGroup, the ViewModel that serves as the DataContext for the group must implement ISupportsRibbonItems. Each object in the "Items" collection, must have their DataContext set to an IRibbonItemViewModel or at a minimum implement ISupportsHidingViaUserPrefs.

Storing State Data for Ribbon Components

State data is data that you want to save between MicroStation design sessions. To store the state data of ribbon components into the common ribbon state file typically named "MstnRibbonState.xml" if not overridden by variable MS_RIBBONPREFS the following procedure can be followed:

  1. Define a class to get/set your state data properties.
  2. Define ECProperties within an ECClass that is uniquely named for your provider.
  3. Add the ECClass to the ECSchema that is provided by Bentley.MicroStation.Ribbon.dll in the static property Bentley.MstnPlatformNET.Ribbon.RibbonState.Schema
  4. Set up C# Properties that get and set values in the instance specific to your provider.
  5. If a property value is changed call RibbonState.RibbonStateData.Dirty = true; to force the state file to be rewritten when the MicroStation session is closed.

    Example - Defining Ribbon Component Provider State Data

    The following code is an example implementate of a ViewGroupHistoryState class for the ViewGroupHistory Ribbon Component provider. This can serve as a template for other RibbonComponentProviders.

    /*--------------------------------------------------------------------------------------+
    |
    | $Source: docs/Articles/APIIntroductionMDL.h $
    |
    | $Copyright: (c) 2017 Bentley Systems, Incorporated. All rights reserved. $
    |
    +--------------------------------------------------------------------------------------*/
    namespace Bentley.ViewGroupHistory
    {
    using System;
    using Bentley.ECObjects;
    using Bentley.ECObjects.XML;
    using Bentley.ECObjects.Schema;
    using Bentley.ECObjects.Instance;
    using System.IO;
    using System.Xml;
    using Bentley.DgnPlatformNET;
    using System.Collections.Generic;
    using Bentley.MstnPlatformNET.Ribbon;
    /*====================================================================================**/
    /*==============+===============+===============+===============+===============+======*/
    public sealed class ViewGroupHistoryState
    {
    private static ViewGroupHistoryState s_state;
    // Name of Class to be added to the RibbonState schema. This must be unique across all RibbonComponent Providers
    private const string s_StateClassName = @"ViewGroupHistoryState";
    // Set up const strings for all the name of all ECProperties that will be needed to hold out state data
    private const string s_propname_AllDropDownWidth = @"AllDropDownWidth";
    private const string s_propname_AllDropDownHeight = @"AllDropDownHeight";
    private const string s_propname_PreviousDropDownWidth = @"PrevDropDownWidth";
    private const string s_propname_PreviousDropDownHeight = @"PrevDropDownHeight";
    private const string s_propname_NextDropDownWidth = @"NextDropDownWidth";
    private const string s_propname_NextDropDownHeight = @"NextDropDownHeight";
    // Private methods
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private ViewGroupHistoryState ()
    {
    // Get the default RibbonState schema and define the class the will hold the state
    // values for the component this assemble provides.
    ECSchema schema = RibbonState.Schema;
    if (null != schema)
    LoadViewGroupHistoryStateClass (schema);
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private void RegisterProperty (IECClass stateClass, string name, IECPrimitiveType type)
    {
    stateClass.Add (new ECProperty (name, type));
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private void LoadViewGroupHistoryStateClass (ECSchema schema)
    {
    ECClass stateClass = new ECClass (s_StateClassName);
    RegisterProperty (stateClass, s_propname_AllDropDownWidth, ECObjects.DoubleType);
    RegisterProperty (stateClass, s_propname_AllDropDownHeight, ECObjects.DoubleType);
    RegisterProperty (stateClass, s_propname_PreviousDropDownWidth, ECObjects.DoubleType);
    RegisterProperty (stateClass, s_propname_PreviousDropDownHeight, ECObjects.DoubleType);
    RegisterProperty (stateClass, s_propname_NextDropDownWidth, ECObjects.DoubleType);
    RegisterProperty (stateClass, s_propname_NextDropDownHeight, ECObjects.DoubleType);
    schema.AddClass (stateClass);
    schema.TrimToSize ();
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private IECInstance StateInstance
    {
    get
    {
    return RibbonState.RibbonStateData.GetOrCreateInstanceByClassName (s_StateClassName);
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private string GetPropertyAsString (string name, string defaultValue="")
    {
    return ECInstanceHelper.GetInstanceStringValue (StateInstance, name, defaultValue);
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private void SetPropertyString (string name, string value)
    {
    IECInstance instance = StateInstance;
    IECPropertyValue propVal = instance[name];
    if (propVal.IsNull || value != propVal.StringValue)
    {
    instance[name].StringValue = value;
    RibbonState.RibbonStateData.Dirty = true;
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private double GetPropertyAsDouble(string name, double defaultValue=0.0)
    {
    return ECInstanceHelper.GetInstanceDoubleValue (StateInstance, name, defaultValue);
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private void SetPropertyDouble (string name, double value)
    {
    IECInstance instance = StateInstance;
    IECPropertyValue propVal = instance[name];
    if (propVal.IsNull || value != propVal.DoubleValue)
    {
    instance[name].DoubleValue = value;
    RibbonState.RibbonStateData.Dirty = true;
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private double GetPropertyAsInt (string name, int defaultValue=0)
    {
    return ECInstanceHelper.GetInstanceIntValue (StateInstance, name, defaultValue);
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private void SetPropertyInt (string name, int value)
    {
    IECInstance instance = StateInstance;
    IECPropertyValue propVal = instance[name];
    if (propVal.IsNull || value != propVal.IntValue)
    {
    instance[name].IntValue = value;
    RibbonState.RibbonStateData.Dirty = true;
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private bool GetPropertyAsBool (string name, bool defaultValue=false)
    {
    return ECInstanceHelper.GetInstanceBoolValue (StateInstance, name, defaultValue);
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    private void SetPropertyBool (string name, bool value)
    {
    IECInstance instance = StateInstance;
    IECPropertyValue propVal = instance[name];
    if (propVal.IsNull || value != (bool)propVal.NativeValue)
    {
    instance[name].NativeValue = value;
    RibbonState.RibbonStateData.Dirty = true;
    }
    }
    // Public methods and properties
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public static ViewGroupHistoryState StateData
    {
    get
    {
    if (null == s_state)
    s_state = new ViewGroupHistoryState ();
    return s_state;
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public double AllDropDownWidth
    {
    get
    {
    return GetPropertyAsDouble (s_propname_AllDropDownWidth, 200);
    }
    set
    {
    SetPropertyDouble (s_propname_AllDropDownWidth, value);
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public double AllDropDownHeight
    {
    get
    {
    return GetPropertyAsDouble (s_propname_AllDropDownHeight, 180);
    }
    set
    {
    SetPropertyDouble (s_propname_AllDropDownHeight, value);
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public double PreviousDropDownWidth
    {
    get
    {
    return GetPropertyAsDouble (s_propname_PreviousDropDownWidth, 200);
    }
    set
    {
    SetPropertyDouble (s_propname_PreviousDropDownWidth, value);
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public double PreviousDropDownHeight
    {
    get
    {
    return GetPropertyAsDouble (s_propname_PreviousDropDownHeight, 180);
    }
    set
    {
    SetPropertyDouble (s_propname_PreviousDropDownHeight, value);
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public double NextDropDownWidth
    {
    get
    {
    return GetPropertyAsDouble (s_propname_NextDropDownWidth, 200);
    }
    set
    {
    SetPropertyDouble (s_propname_NextDropDownWidth, value);
    }
    }
    /*------------------------------------------------------------------------------------**/
    /*--------------+---------------+---------------+---------------+---------------+------*/
    public double NextDropDownHeight
    {
    get
    {
    return GetPropertyAsDouble (s_propname_NextDropDownHeight, 180);
    }
    set
    {
    SetPropertyDouble (s_propname_NextDropDownHeight, value);
    }
    }
    } // ViewGroupHistoryState
    } //namespace Bentley.ViewGroupHistory

    Example MstnRibbonState.xml file

    Below is an example state xml file that contains data from two RibbonCoponent Providers.

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <!--Bentley MstnRibbonState Configuration File.-->
    <!--Modifying this file may render it invalid.-->
    <RibbonState>
    <RibbonViewState xmlns="RibbonState.01.00">
    <ActiveWorkFlowName>Drawing</ActiveWorkFlowName>
    <RibbonMinimizedState>False</RibbonMinimizedState>
    <LineStylePickerShowSearch>True</LineStylePickerShowSearch>
    <LineStylePickerShowRecentStyles>True</LineStylePickerShowRecentStyles>
    <LineStylePickerDisplayMode>All</LineStylePickerDisplayMode>
    <LineStylePickerDropDownWidth>180</LineStylePickerDropDownWidth>
    <LineStylePickerDropDownHeight>500</LineStylePickerDropDownHeight>
    </RibbonViewState>
    <ViewGroupHistoryState xmlns="RibbonState.01.00">
    <PrevDropDownWidth>200</PrevDropDownWidth>
    <PrevDropDownHeight>180</PrevDropDownHeight>
    </ViewGroupHistoryState>
    </RibbonState>

Copyright © 2017 Bentley Systems, Incorporated. All rights reserved.