Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

About a 2015 sample (indicator/strategy opens window) by NinjaTrader_ChelseaB

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    About a 2015 sample (indicator/strategy opens window) by NinjaTrader_ChelseaB

    Hey, guys.
    I found a sample on a currently closed forum (link below). The script opens a window from a strategy.
    I have tested this code in an indicator and it also works. I found it very convenient.
    What I would like to know is if it is possible to save the location and size of the window created in the workspace since it is not possible to implement "IWorkspacePersistence".
    Thanks​

    Link:

    #2
    Hello rafaelcoisa,

    The only way to work with the workspace is to create your window in the same way as shown in the help guide addon samples which use IWorkspacePersistance. You would need to use an NTWindow class to have that persistence.



    JesseNinjaTrader Customer Service

    Comment


      #3
      Hey NinjaTrader_Jesse,

      My goal is to show the indicator variables in a window like in the "DataBox" (without the mouse feature) implementing the IWorkspacePersistance.

      But, because of the "default constructor" thing, I can't do this:
      Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.


      And, if I use some solution with "static", I can only use the indicator on a single chart.

      Is there any other solution?​

      Comment


        #4
        Hello rafaelcoisa,

        If you are having trouble using the constructor you could just remove it. You can make pubic properties or methods to set values in your class.

        JesseNinjaTrader Customer Service

        Comment


          #5
          Hey NinjaTrader_Jesse

          Is it possible to pass information from the Indicator class properties to the window class without the constructor and still do the "setbinding"? In the pastebin example I do this communication with the window's constructor:

          window constructor:
          public Win(NinjaScriptBase ninjaScript, string property)

          window creation inside the indicator class:
          new WPFwindow.Win(this, "StringValue").Show();

          which allows me to do the setbinding.​

          Comment


            #6
            Hello rafaelcoisa,

            While I can't recommend anything for using bindings you can instead use the approach the addon sample uses which just uses logic in the C# code to set the UI values. The general expectation for any new window developed directly in NinjaScript would be to use an NTWindow to gain the window styles and also interfaces for platform features. To create the UI in xaml and then the code which creates the window loads and parses that xaml to create the content. That parsed xaml can be used to grab UI variable instances so your code can set the values in the UI.

            https://ninjatrader.com/support/help...t_overview.htm

            You can see that by searching for LoadXAML in the addon sample basic. The same concept could be used in a single window instead of the TabPage shown in that sample. You just apply the parsed xaml as the content of the window: Content = LoadXAML();

            n the LoadXaml function the controls are found like the following so you can use them to get or set values:

            Code:
            acctValuesButton = LogicalTreeHelper.FindLogicalNode(pageContent, "acctValuesButton") as Button;
            I would suggest to remove the constructor you added and make a custom public method that you can use for passing in data and invoking any logic you need.

            Instead of:

            Code:
            public Win(NinjaScriptBase ninjaScript, string property)
            {​
            }
            use

            Code:
            public MyCustomMethodName(NinjaScriptBase ninjaScript, string property)
            {
            }
            If we then assume you want to set the some controls property:

            Code:
            public MyCustomMethodName(NinjaScriptBase ninjaScript, string property)
            {
                 SomeControl.Text = someText;
            }
            You could then call that method after creating the instance of the window.

            Code:
            Win myWindow = new WPFwindow.Win();
            myWindow.Show();
            myWindow.MyCustomMethodName(this, "StringValue");
            ​​
            JesseNinjaTrader Customer Service

            Comment


              #7
              Hey NinjaTrader_Jesse,

              I didn't put in the code the "DependencyObject", XAML and etc to make my problem easier to visualize, I'm aware of that.

              Here, a pastebin with a TextBlock control:
              Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.


              I tried what you suggested (see code above). But it did not work. After compilation, if you reload the chart and open the custom window, the text "aaa" will appear in the "textblock". But, if you close NinjaTrade, save the workspace and reopen it. The custom window opens, but the text block control with the text "aaa" does not. And I think that happens because you create the window inside a variable. I'm mentioning this at the beginning of the code:

              private WPFwindow.Win win;

              which allows that:

              win = new WPFwindow.Win();
              win.Show();
              win.MyCustomMethodName("aaa");​​

              Comment


                #8
                Hello rafaelcoisa,

                You are not using the IWorkspcae methods to do any saving or loading, the platform doesn't know you want anything saved. The example in the help guide expects that you added something to the main tab control like a tab page, that is the MainTabControl.SaveToXElement(element); If you just have a window you don't have anything added to the tab control so that's saving nothing.

                Anything custom you want saved will need to implement you own custom saving/loading logic inside the methods Save and Restore.

                You can see a sample of a no tab window along with loading/parsing/using xaml controls and saving/restoring values here: https://ninjatrader.com/support/foru...830#post759830

                Using a method would still be the suggested way to pass data or invoke actions inside your window from the calling script.
                JesseNinjaTrader Customer Service

                Comment


                  #9
                  Hey NinjaTrader_Jesse,

                  It's weird that I need a "tabControl" to save and restore a custom window.
                  When I tested the same code that I shared on pastebin, but with a static class to make the communication between the indicator class and the window class, the IWorkspacePersistence saved and restored the custom window and no use of "tabControl" was needed. Also, in the code of "AddonShellExampleNoTabs.cs", there is only one line of code that mentions a "tabControl":

                  TabControl private tabControl;

                  But, that line is not used.

                  Also, if you look at the dispatcher that opens the window in "AddonShellExampleNoTabs.cs":

                  Globals.RandomDispatcher.InvokeAsync(new Action(() => new AddonShellNoTabsExampleWindow().Show()));

                  You see that no variables are used to instantiate the window.

                  So maybe the "IWorkspacePersistence" is not working for another reason.​

                  Comment


                    #10
                    Hello rafaelcoisa,

                    You don't need a tab control.

                    If you take a look at the AddonShellNoTabsExampleWindow there is a simple window and it that shows everything from making xaml controls to saving their values. The help guide samples are in reference to the addon sample basic which has tabs and is also in the help guide. What you are asking for is not exactly like that so you need to modify what you are doing to be like the AddonShellNoTabsExampleWindow.

                    The AddonShellNoTabsExampleWindow does not pass anything in a constructor and doesn't need to reference anything in the calling script so that's why its Show is in that simple form. For your use case you could use the code that I provided as a way to pass data while also opening the window.

                    Your window and its content need to be created first using the LoadXaml method, once the window is created and elements are there you can use a custom method to reset their values from an external context like the calling script.

                    You will end up with something similar to the following in both the restore and save methods.

                    Code:
                    XElement exampleCheckBoxElement = itemsRootNode.Element("exampleCheckBoxElement");
                    if (exampleCheckBoxElement != null)
                    exampleCheckBox.IsChecked = Boolean.Parse(exampleCheckBoxElement.Value);​
                    JesseNinjaTrader Customer Service

                    Comment


                      #11
                      Hey, NinjaTrader_Jesse,

                      But why are all my controls and data restored when communication between indicator class and window class is done by static class or singleton? When using static class or singleton to communicate indicator class and window class, I don't need to add anything here:

                      public void Restore(XDocument document, XElement element)
                      {
                      if (MainTabControl != null)
                      MainTabControl.RestoreFromXElement(element);
                      }

                      public void Save(XDocument document, XElement element)
                      {
                      if (MainTabControl != null)
                      MainTabControl.SaveToXElement(element);
                      }​

                      Comment


                        #12
                        Hello rafaelcoisa,

                        You should be coping the AddonShellNoTabsExampleWindow essentially in its entirety for what you are trying to do.

                        Static is basically never used in NinjaScript because that C# concept goes against how the scripts in NinjaTrader work. Everything in NinjaScript runs off of instances, with static there are no instances.

                        The AddonShellNoTabsExampleWindow is the correct path for making a custom window and saving/loading values that would be unique to each window. That means that you could run this from many charts in the workspace and each chart could have its own unique window and save its own unique values as you specify in the Save and Restore methods. When you don't use tabs in your window it would not be expected for you to try and use the MainTabControl.SaveToXElement(element);, you would instead do like the AddonShellNoTabsExampleWindow and just write your own save/load xml logic.

                        If you then need to pass data or update values in the class you can make public methods or properties in that window class which your indicator can call. That is different than the AddonShellNoTabsExampleWindow and would be how I showed it post 6.


                        JesseNinjaTrader Customer Service

                        Comment


                          #13
                          Hey NinjaTrader_Jesse,

                          I know about the static/ninjatrader relationship​ (found it here: https://ninjatrader.com/support/foru...lass-recompile).
                          I'm constantly referring to the singleton because it shows what problem I have when trying to implement "IWorkspacePersistence". Part of what I'm trying to do is not use any static solutions as I mentioned at the beginning.

                          Let me clear things up a bit first.

                          What does "AddonShellNoTabsExampleWindow" do?

                          It creates an instance of a custom window, manipulates the data generated by that instance, saves it to the XML file, and restores it when it starts the restoration process.
                          For example, if an "int" is 10, you save 10 in the XML file, and while restoration of the workspace, ninjatrader will create a new instance of the window, read the XML (the number 10 will literally be in the file) and restore it.

                          I guess you think I'm trying to do this. But it's not the case. If that were the case, you'd be right. Just add some code in the Restore/Save methods and you're good to go. I already knew.

                          What I'm trying to make is a custom window like NinjaTrader's "DataBox" window as I mentioned at the beginning. And I did the live data part. The indicator I shared with you works. It shows live data of an indicator variable in the custom window.

                          Now, what still remains to be done is to implement the window restoration part.

                          If you open the "DataBox", close ninjatrader, save the workspace and reopen it, the "DataBox" will be restored and can already show the live data. No specific values for closes, highs and lows were saved in the XML file because there is no point in doing so.

                          What's the difference between what I want to do and the "DataBox"?

                          Live data in the "DataBox" is mouse driven. When reopening ninjatrader, the "DataBox" window is restored, but there is no data in the "DataBox". Then you place your mouse over some bar on the chart and the live data is triggered.

                          In my case, what triggers the live data is the indicator instance where the variables (properties implemented with "INotifyPropertyChanged") exist.

                          And here's the point.

                          When the restoration process starts, I think ninjatrader creates an instance of the custom window directly with its constructor, which is why the constructor of the custom window needs to be a "default constructor" because no reference to the instance of anything else can be made there because ninjatrader cannot identify where this instance will be in memory.

                          However, when you use a singleton to bridge the indicator class instance and the custom window class instance, the triggering of live data on the restored custom window occurs because the indicator and custom window will reference the instance singleton in the static memory that was there before the window instance and the indicator instance were created.

                          It is possible to call a window of the indicator class, bind data, etc. What I think is not possible is to use "IWorkspacePersistence" to restore the customized window because the customized window during its restoration has no way of referencing the indicator instance where the variables (properties implemented with "INotifyPropertyChanged") that will be shown in the window exist.

                          Do you see the problem?​

                          Comment


                            #14
                            Hello rafaelcoisa,

                            The sample that I linked to is the way that is suggested to create windows that have no tabs and also can be saved with the workspace. If we go back to post 1 and your original question that sample already does exactly what you asked:

                            What I would like to know is if it is possible to save the location and size of the window created in the workspace since it is not possible to implement "IWorkspacePersistence".

                            If you try the sample it already does this, you don't need to add any other code for the size and location. The workspace manages that. You need to implement IWorkspacePersistence on the window class for that to work. You can use the Save/Restore methods for any other custom values that needs saved/restored.

                            To make that window like a databox you would need to have your indicator call methods inside your window class to update the values of the UI. If you need live values like market data then you really don't need to save anything, just have the indicator control the window by using your custom methods.

                            The existing databox is managed by the chart so you really cant use that as an example of what to do in your own code, you will need to make something custom to do something similar. The best way to update your window class values would be using methods like described in post 6. Your indicator needs to drive any updates because you want it to act similar to a databox where the chart drives the databox.

                            You don't need to add a custom constructor here because you can just make as many custom methods as needed. As mentioned we cant help with WPF bindings but you can use the approach shown in the sample that we have been discussing. Its expected that you save a control to a variable and then use that variable to get or set values to the control, we have no specific guidelines for bindings/inotifypropertychanged because NinjaScript does not compile xaml and that codding pattern was never intended to be used in this context.




                            JesseNinjaTrader Customer Service

                            Comment


                              #15
                              Hey NinjaTrader_Jesse,

                              Here a better example:


                              the "SetIndicatorValueFromAddonWindowExampleToolsWindo w" sample.

                              The addon sends information to the indicator.
                              In the window dispatcher inside the indicator there is an explicit reference to the indicator.

                              What I'm trying to do is the opposite. Send information from the indicator to the addon.

                              Where should I put that reference?​

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by martin70, 03-24-2023, 04:58 AM
                              14 responses
                              105 views
                              0 likes
                              Last Post martin70  
                              Started by TraderBCL, Today, 04:38 AM
                              0 responses
                              2 views
                              0 likes
                              Last Post TraderBCL  
                              Started by Radano, 06-10-2021, 01:40 AM
                              19 responses
                              606 views
                              0 likes
                              Last Post Radano
                              by Radano
                               
                              Started by KenneGaray, Today, 03:48 AM
                              0 responses
                              4 views
                              0 likes
                              Last Post KenneGaray  
                              Started by thanajo, 05-04-2021, 02:11 AM
                              4 responses
                              470 views
                              0 likes
                              Last Post tradingnasdaqprueba  
                              Working...
                              X