Providing UI Elements for WL8 Extensions
WL8 supports cross-platform development by enforcing a separation of core logic components and user-interface (WPF) components. WL8's core logic library is WealthLab.Core, which is platform neutral. Although it contains components that require configuration, such as Historical Data Providers and Broker Providers (the Dummy Broker) it does not contain the UI elements to configure these items.
These UI editors exist in a secondary assembly, WealthLab.WPF, which targets Windows. WL8 uses classes that derive from ObjectEditorBase to establish a bridge between the logical components and their editors. ObjectEditorBase provides several possible points of integration for WL8 components:
- Custom Settings panels for components like Historical Data Providers that might need to be configured by the user.
- New DataSet Wizard pages for Historical Data Providers, so that DataSet configuration can be collected in the WL8 New DataSet Wizard.
- BarGlyphs that Event Providers can register to display their Events on the chart in unique ways.
- Platform Methods that any component can call from a platform-neutral logical assembly.
Developing an ObjectEditorBase Class
If you develop components that require custom configuration, or some other interaction with the WL8 UI as described in the points above, you'll need to create a new class derived from ObjectEditorBase in your extension's class library. Override the Name property to return the exact same Name as the component you are supporting. Every configurable component in WL8 ultimately derives from the base class Configurable, which exposes a Name property as well.
Custom Editor Panels
The Configurable class has two modes of operation, controlled by the value of its ConfigurableType property:
- ParameterList - The component uses its Parameters property, which is a List of Parameter instances. The Parameter instances should be created in the component's GenerateParameters method override.
- VanillaString - The component does not use the Parameters, but instead expresses its configuration as a single string, stored in its Configuration property.
A Custom Editor Panel is used whenever a component must be configured by the user. For example, Historical Data Providers display their Custom Editor Panel whenever you click them in the Data Manager. Whereas Broker Providers display them in a dialog box when the user clicks Configure in the Order Manager.
Do I Need a Custom Editor Panel?
If your component uses the ParameterList option, you need not create your own Custom Editor Panel. WL8 will use a default Parameter Editor Panel for your component. However, if you wish to use the VanillaString option, you'll need to provide a Custom Editor Panel and surface it in your ObjectEditorBase derived class. You might also want to provide your own Editor even if your component does use ParameterList, perhaps in order to use a special UI you feel would work better for your component.
public virtual ICustomSettingsEditor GetCustomSettingsEditor()
Override this method in your ObjectEditorBase descendant to return an instance of a WPF UserControl that implements the ICustomSettingsEditor interface. This interface provides a means for your Editor Panel to communicate state back to WL8.
New DataSet Wizard Pages
If you are creating a Historical Data Provider component, you can implement the methods below to provide integration with WL8's New DataSet Wizard. When the user selects your Provider in the New DataSet Wizard and clicks Next, the Wizard Page(s) you return in the methods below will appear in the Wizard.
Do I Need Custom Wizard Pages?
If the DataSets that your Historical Data Provider works with do not require any special configuration, besides a list of symbols that the user can enter, you need not provide your own Wizard Pages. WL8 will use a default Wizard Page allowing the user the enter the symbols.
What is a DSString?
Each DataSet maintains its configuration information in a string property called DSString. Your implementation of the methods in this section will ultimately deliver a DSString that is based on the selections and input the user entered into your Wizard Page(s).
public virtual void InitializeNewDataSetWizard(DataSet ds = null)
Override this method to perform any required initialization that should occur when the New DataSet Wizard is first initialized with your Historical Data Provider selected. If the ds parameter contains a DataSet instance, you should populate your Wizard Page controls with the configuration based on the DataSet's DSString property.
public virtual UserControl GetFirstWizardPage()
Override this method to return the first Wizard Page that should appear. Each Wizard Page is a class derived from WPF UserControl. You'll typically create the Wizard Page instance(s) in the InitializeNewDataSetWizard methbod.
public virtual bool CanAdvanceToNextPage(UserControl page, ref string errorMessage)
WL8 calls this method when the user clicks Next from one of your Wizard Pages in the New DataSet Wizard. You should check the input entered by the user and return true if everything on the Wizard Page passed in the page parameter looks valid. If there are any problems, return false, and assign an error message to the errorMessage ref parameter.
public virtual UserControl GetNextWizardPage(UserControl page)
Assuming the CanAdvanceToNextPage above returned true, WL8 then calls this method to obtain the next Wizard Page, the one that should be shown immediately after the Page in the page parameter. If your Wizard implementation contains only a single Page, you need not override this method. If the page parameter represents the last Wizard Page, return null.
public virtual bool IsLastWizardPage(UserControl page)
Return true if the Wizard Page in the page parameter represents the last Wizard Page in the sequence. The default return value is true, so if your implementation uses only a single Page, you need not override this method.
public virtual string GetWizardDSString()
Override this method to return the fully composed DSString, which should be based on the information entered by the users into the UI controls in your Wizard Page(s).
BarGlyphs for Custom Event Types
public virtual object GetEventBarGlyph(EventDataPoint edp)
If you are building an Event Provider, one of ways to customize the experience is to render your Events using a unique visual glyph on the chart. WL8 uses standard glyphs for Events, but you can control the visual presentation by overriding this method. Check the EventDataPoint provided in the edp parameter, and return a new instance of a class derived from BarGlyphBase that should be used to represent the item on the chart.
public virtual object ExecutePlatformMethod(string methodName, object parameter)
Components in a platform-neutral library can make calls to a platform-specific method by using the ExecutePlatformMethod method in the IHost interface. WL8 will look for a matching method in an ObjectEditorBase, execute the method if found, and return the result back to the caller.
For example, the Interactive Brokers Broker Provider is defined in a platform-neutral library WealthLab.InteractiveBrokers. But it contains a call to attempt to open IB's TWS, which is a purely Windows task. In order to achieve this, the Broker Provider calls WLHost.Instance.ExecutePlatformMethod passing a method name of "OpenTWS". A second assembly, WealthLab.InteractiveBrokers.WPF contains an ObjectEditorBase derived class that pairs with the IB Broker Provider. The ObjectEditorBase descendant implements ExecutePlatformMethod, and looks for the name "OpenTWS" in the methodName parameter. It proceeds to attempt to open IB's TWS, and returns the success or failure back as the return value.