I've been following the documentation here: https://ninjatrader.com/support/help...development_ov erview.htm
I'm at a point where I get this error when I click on my menu item in the "New" section: (see attached).
This is the AddOn:
#region Using declarations
using System;
using NinjaTrader.Gui.Tools;
using System.Windows;
using NinjaTrader.Gui;
using System.Windows.Controls;
using System.Xml.Linq;
using System.Windows.Media;
#endregion
//This namespace holds Add ons in this folder and is required. Do not change it.
namespace NinjaTrader.NinjaScript.AddOns
{
public class MyCustomAddOn : AddOnBase
{
// menu stuff
private NTMenuItem MenuItem;
private NTMenuItem ControlCenterNewMenu;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Enter the description for your new custom Add on here.";
Name = "CustomeAddOn";
}
else if (State == State.Configure)
{
}
else if (State == State.DataLoaded)
{
}
else if (State == State.Terminated)
{
}
}
protected override void OnWindowCreated(Window window)
{
// We want to place the menu item for the AddOn in the Control Center's "New" menu
// First obtain a reference to the Control Center window
ControlCenter cc = window as ControlCenter;
if (cc == null)
return;
/* Determine we want to place the AddOn in the Control Center's "New" menu
Other menus can be accessed via the control's "Automation ID". For example: toolsMenuItem, workspacesMenuItem, connectionsMenuItem, helpMenuItem. */
ControlCenterNewMenu = cc.FindFirst("ControlCenterMenuItemNew") as NTMenuItem;
if (ControlCenterNewMenu == null) return;
// 'Header' sets the name of our AddOn seen in the menu structure
MenuItem = new NTMenuItem { Header = "Custom Addon", Style = Application.Current.TryFindResource("MainMenuItem") as Style };
// Add our AddOn into the "New" menu
ControlCenterNewMenu.Items.Add(MenuItem);
MenuItem.Click += OnMenuItemClick;
}
private void OnMenuItemClick(object sender, EventArgs e)
{
Core.Globals.RandomDispatcher.BeginInvoke(new Action(() => new ExporterWindow().Show()));
}
// Class for Window management
// create a NT8 window with the name StableMetricsWindow
// this window will be used to display the prometheus URL
public class ExporterWindow : NTWindow
{
public ExporterWindow()
{
Caption = "Custom Addon Window";
Width = 800;
Height = 600;
TabControl tc = new TabControl();
// Attached properties defined in TabControlManager class should be set to achieve tab moving, adding/removing tabs
//TabControlManager.SetIsMovable(tc, true);
//TabControlManager.SetCanAddTabs(tc, true);
//TabControlManager.SetCanRemoveTabs(tc, true);
// if ability to add new tabs is desired, TabControl has to have attached property "Factory" set.
TabControlManager.SetFactory(tc, new AddOnFrameworkWindowFactory());
Content = tc;
/* In order to have link buttons functionality, tab control items must be derived from Tools.NTTabPage
They can be added using extension method AddNTTabPage(NTTabPage page) */
tc.AddNTTabPage(new AddOnFrameworkTab());
}
}
/* Class which implements Tools.INTTabFactory must be created and set as an attached property for TabControl
in order to use tab page add/remove/move/duplicate functionality */
public class AddOnFrameworkWindowFactory : INTTabFactory
{
// INTTabFactory member. Required to create parent window
public NTWindow CreateParentWindow()
{
return new ExporterWindow();
}
// INTTabFactory member. Required to create tabs
public NTTabPage CreateTabPage(string typeName, bool isTrue)
{
return new AddOnPage();
}
}
public class AddOnFrameworkTab : NTTabPage
{
public AddOnFrameworkTab()
{
AddOnFrameworkWindowFactory myAddOnFrameworkWindowFactory = new AddOnFrameworkWindowFactory();
Content = myAddOnFrameworkWindowFactory.CreateTabPage("AddOnPage", true);
}
// implement a basic save
protected override void Save(XElement element)
{
// Save the tab page
if (element == null)
return;
}
// implement a basic restore
protected override void Restore(XElement element)
{
// Restore the tab page
if (element == null)
return;
}
// implement a basic GetHeaderPart
protected override string GetHeaderPart(string header)
{
return "AddOnTab";
}
}
public class AddOnPage : NTTabPage
{
public AddOnPage()
{
// create the parent window
Grid grid = new Grid();
grid.Background = new SolidColorBrush(Colors.Transparent);
ColumnDefinition col1 = new ColumnDefinition();
// bug in the NT documentation, missing a space here
col1.Width = new GridLength(55);
ColumnDefinition col2 = new ColumnDefinition();
// bug in the NT documentation, missing a space here
col2.Width = new GridLength(45);
grid.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);
// Create a textblock to display the prometheus URL
TextBlock textBlock = new TextBlock();
textBlock.Text = "Some Text: ";
}
// implement a basic save
protected override void Save(XElement element)
{
// Save the tab page
if (element == null)
return;
}
// implement a basic restore
protected override void Restore(XElement element)
{
// Restore the tab page
if (element == null)
return;
}
// implement a basic GetHeaderPart
protected override string GetHeaderPart(string header)
{
return "AddOnTab";
}
}
// Will be called as a new NTWindow is destroyed. It will be called in the thread of that window
protected override void OnWindowDestroyed(Window window)
{
if (MenuItem != null && window is ControlCenter)
{
if (ControlCenterNewMenu != null && ControlCenterNewMenu.Items.Contains(MenuItem))
ControlCenterNewMenu.Items.Remove(MenuItem);
MenuItem.Click -= OnMenuItemClick;
MenuItem = null;
}
}
}
}
I'm not using a XAML file. I'm opting to do everting in code. I don't care about persistence in the workspace, so took that out as well. The tab would be simple, so took out the create, move, delete options from TabControl.
Google searched point to XML errors and such. I'm VERY much not a UI / FrontEnd sort of person, so all lot of this is a bit new and overwhelming.
Cheers!

Comment