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

Changing Tab Colour

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

    Changing Tab Colour

    Hi,

    I'm hoping someone can help, as I'm a bit stuck. I have a strategy that I want to change the colour of its tab in the chart window. It works, but only if I enable the strategy directly from the chart. If I enable the strategy from the Control Centre then I get the following error:

    "The calling thread cannot access this object because a different thread owns it"

    I can add the strategy from the chart (by clicking the strategy button) without enabling it, and it appears in Control Centre as you would expect. But if I then tick the box in control centre to enable it, I get the error. But, if I bring up the strategy window from the chart and enable it that way instead, it works fine.

    Also, after the error has occurred, if I just refresh the chart (by pressing F5) then it works fine. But, disabling and re-enabling from Control Centre creates the error. I've tried to strip down the code as much as possible to isolate the issue, and copied below (also attached). Also note that I only see the error in Visual Studio; it doesn't appear in the output or log (but the tab won't change colour as a result).

    I suspect that I need to somehow call the dispatcher from a different thread (whatever Control Centre is using perhaps), but the dispatcher and thread name are saying it's correct...

    I'm so close to this working! Any ideas?


    public class TabTest4 : Strategy
    {
    private Style redstyle;
    private Style defaultstyle;

    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Name = "TabTest4";
    Calculate = Calculate.OnEachTick;
    }
    else if (State == State.Configure)
    {
    string customResources = @"
    <ResourceDictionary xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
    <Style TargetType=""{x:Type TabItem}"" x:Key=""RedStyle"">
    <Setter Property=""BorderThickness"" Value=""0""/>
    <Setter Property=""Padding"" Value=""0"" />
    <Setter Property=""HeaderTemplate"">
    <Setter.Value>
    <DataTemplate>
    <Border x:Name=""grid"" Background=""Red"">
    <ContentPresenter>
    <ContentPresenter.Content>
    <TextBlock Margin=""4"" FontSize=""15"" Text=""{TemplateBinding Content}""/>
    </ContentPresenter.Content>
    </ContentPresenter>
    </Border>
    <DataTemplate.Triggers>
    <DataTrigger Binding=""{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TabItem}},Path=IsSelected}"" Value=""True"">
    <Setter TargetName=""grid"" Property=""Background"" Value=""Red""/>
    </DataTrigger>
    </DataTemplate.Triggers>
    </DataTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </ResourceDictionary>";
    ResourceDictionary rd = XamlReader.Parse(customResources) as ResourceDictionary;
    redstyle = rd["RedStyle"] as Style;
    }
    else if (State == State.Terminated) //set the tab back to standard once we are finished
    {
    if (ChartControl != null && defaultstyle != null)
    {
    this.Dispatcher.InvokeAsync(() =>
    {
    var chartWindow = Window.GetWindow(ChartControl.Parent) as Chart;
    foreach (TabItem tab in chartWindow.MainTabControl.Items)
    {
    if (tab.Header.ToString() == Instrument.FullName)
    {
    tab.Style = defaultstyle;
    break;
    }
    }
    });
    }
    }
    }

    protected override void OnBarUpdate() //runs fine when enabling strategy from chart, but not from control centre
    {
    if (State == State.Realtime)
    {
    if (ChartControl != null)
    {
    this.Dispatcher.InvokeAsync(() =>
    {
    var chartWindow = Window.GetWindow(ChartControl.Parent) as Chart;
    foreach (TabItem tab in chartWindow.MainTabControl.Items)
    {
    if (tab.Header.ToString() == Instrument.FullName)
    {
    if (tab.Style != redstyle) defaultstyle = tab.Style;
    tab.Style = redstyle; //error occurs here
    break;
    }
    }
    });
    }
    }
    }
    }
    Attached Files

    #2
    Hello beastment,

    Thanks for your post and providing the example so we can have a look as well. WPF modifications begin to escape the scope of support we may provide, but your inquiry is more focused on the threading issue.

    I generally would call ChartControl.Dispatcher.InvokeAsync(), but when I test your strategy when adding/enabling from a chart and from the Strategies Tab, I do not encounter the error.

    Demo - https://www.screencast.com/t/UOyywXMEVUsz

    Could you confirm if you are on the latest version of NinjaTrader? (R15)

    Update installers can be downloaded here: https://ninjatrader.com/PlatformDirect

    For the thread's reference, Multi Threading Considerations are documented here - https://ninjatrader.com/support/help...-threading.htm

    I look forward to being of further assistance.
    JimNinjaTrader Customer Service

    Comment


      #3
      Well, I'll be... Why!?

      Yes, that's exactly what it's supposed to. I've just done a completely clean install of the latest version of NT (cleared out folders in documents and program files as well), installed nothing but the strategy, and I'm still getting the same issue. I even used the same instrument and time period as you for good measure, but it doesn't work for me.

      Clearly it does for you though. What could the difference be?

      Here's what I see:

      https://vimeo.com/282972240

      Comment


        #4
        Hello beastment,

        Testing on 15.1 gives me the same behavior you are witnessing.

        To address the threading issue, you could create the resource just before you apply it to make sure the thread that is applying the resource does in fact own the resource.

        The modification attached appears to work under these circumstances.

        If there is anything else we can do to help, please let us know.
        Attached Files
        JimNinjaTrader Customer Service

        Comment


          #5
          Yes, that's fixed it. I assumed it was the TabItem that was on some mysterious other thread and causing the error, but it looks like it's actually the Style object that was causing the problem. So, the Configure State Change event is running on a different thread to OnBarUpdate?

          No matter, it works!

          Thanks Jim. I'm constantly impressed by the support you folks offer. It must consume a lot of time.

          Cheers,
          Ben.

          Comment


            #6
            Hello beastment,

            State.Configure is called from a UI thread while OnBarUpdate is called in either a thread pool for historical data or an Instrument thread for realtime data. So, yes, State.Configure is called on a separate thread than OnBarUpdate.

            Since the the strategy was being started from the Control Center and not the Chart, the UI thread that was creating the resource was probably a separate UI thread. NinjaTrader creates as many UI threads as there are logical cores. I believe that the first time I attempted, I "got lucky" in the sense that the same UI thread was being used.
            JimNinjaTrader Customer Service

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by bortz, 11-06-2023, 08:04 AM
            47 responses
            1,602 views
            0 likes
            Last Post aligator  
            Started by jaybedreamin, Today, 05:56 PM
            0 responses
            8 views
            0 likes
            Last Post jaybedreamin  
            Started by DJ888, 04-16-2024, 06:09 PM
            6 responses
            18 views
            0 likes
            Last Post DJ888
            by DJ888
             
            Started by Jon17, Today, 04:33 PM
            0 responses
            4 views
            0 likes
            Last Post Jon17
            by Jon17
             
            Started by Javierw.ok, Today, 04:12 PM
            0 responses
            12 views
            0 likes
            Last Post Javierw.ok  
            Working...
            X