Attached is an indicator which adds usercontrols (Grids and Buttons) to the chart, by parsing XAML from and external file (included). The indicator is just a modification of the built-in SMA.
To the left of the chart is a grid containing a Button at its root level, and another inner Grid which also contains a Button of its own. Both buttons work: they double the Period property, and then simulate the pressing of F5 to refresh the chart (via SendKeys).
In the middle of the chart, however, is a control created from that same XAML file, but it extracts just the inner grid and its inner button. Although the button press is detected (it prints to Output window and does change the Period), it doesn't seem to refresh the chart. The only reason I can think of is that it is interfering with SendKeys F5.
Can someone please shed some light?
// // Copyright (C) 2018, NinjaTrader LLC <www.ninjatrader.com>. // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release. // #region Using declarations using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Xml.Serialization; using NinjaTrader.Cbi; using NinjaTrader.Gui; using NinjaTrader.Gui.Chart; using NinjaTrader.Gui.SuperDom; using NinjaTrader.Data; using NinjaTrader.NinjaScript; using NinjaTrader.Core.FloatingPoint; using NinjaTrader.NinjaScript.DrawingTools; #endregion using System.Windows.Markup; using System.IO; using System.Windows.Controls; // This namespace holds indicators in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.Indicators { /// <summary> /// The SMAwithButtons (Simple Moving Average) is an indicator that shows the average value of a security's price over a period of time. /// </summary> public class SMAwithButtons : Indicator { private double priorSum; private double sum; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = NinjaTrader.Custom.Resource.NinjaScriptIndicatorDescriptionSMA; Name = "SMAwithButtons"; IsOverlay = true; IsSuspendedWhileInactive = true; Period = 14; AddPlot(Brushes.Goldenrod, NinjaTrader.Custom.Resource.NinjaScriptIndicatorNameSMA); } else if (State == State.Configure) { priorSum = 0; sum = 0; } else if (State == State.Historical) { if (ChartControl != null ) { ChartControl.Dispatcher.InvokeAsync((Action)(() => { Insert_GridInGrid(); Insert_InnerGridOnly(); })); } } else if (State == State.Terminated) { } } private void DisconnectMyControls() { throw new NotImplementedException(); } private void Insert_GridInGrid() { FileStream fs = new FileStream(System.IO.Path.Combine(NinjaTrader.Core.Globals.UserDataDir, "bin", "Custom", "Indicators", "SMAwithButtons.xaml"), FileMode.Open); Grid rootGrid = (Grid)XamlReader.Load(fs); Button buttonFromFile = LogicalTreeHelper.FindLogicalNode(rootGrid, "OuterButton") as Button; buttonFromFile.Click += ClickDetector; buttonFromFile = LogicalTreeHelper.FindLogicalNode(rootGrid, "InnerButton") as Button; buttonFromFile.Click += ClickDetector; UserControlCollection.Add(rootGrid); } private void Insert_InnerGridOnly() { FileStream fs = new FileStream(System.IO.Path.Combine(NinjaTrader.Core.Globals.UserDataDir, "bin", "Custom", "Indicators", "SMAwithButtons.xaml"), FileMode.Open); Grid rootGrid = (Grid)XamlReader.Load(fs); Grid innerGrid = LogicalTreeHelper.FindLogicalNode(rootGrid, "InnerGrid") as Grid; Button innerButton; //innerButton = LogicalTreeHelper.FindLogicalNode(rootGrid, "InnerButton") as Button; innerButton = LogicalTreeHelper.FindLogicalNode(innerGrid, "InnerButton") as Button; innerButton.Click += ClickDetector; UserControlCollection.Add(innerGrid); //add only innerGrid to usercontrols } private void ClickDetector(object sender, RoutedEventArgs e) { Print("Button received:" + (sender as Button).Content); if (Period > 200) Period = 10; else Period = Period * 2; System.Windows.Forms.SendKeys.SendWait("{F5}"); } protected override void OnBarUpdate() { if (BarsArray[0].BarsType.IsRemoveLastBarSupported) { if (CurrentBar == 0) Value[0] = Input[0]; else { double last = Value[1] * Math.Min(CurrentBar, Period); if (CurrentBar >= Period) Value[0] = (last + Input[0] - Input[Period]) / Math.Min(CurrentBar, Period); else Value[0] = ((last + Input[0]) / (Math.Min(CurrentBar, Period) + 1)); } } else { if (IsFirstTickOfBar) priorSum = sum; sum = priorSum + Input[0] - (CurrentBar >= Period ? Input[Period] : 0); Value[0] = sum / (CurrentBar < Period ? CurrentBar + 1 : Period); } } #region Properties [Range(1, int.MaxValue), NinjaScriptProperty] [Display(ResourceType = typeof(Custom.Resource), Name = "Period", GroupName = "NinjaScriptParameters", Order = 0)] public int Period { get; set; } #endregion } }
Comment