Flex chart axis X scrollbar rendering question

Posted by: a.sharov on 19 September 2022, 12:26 pm EST

    • Post Options:
    • Link

    Posted 19 September 2022, 12:26 pm EST

    Hi.

    I will try to explain my issue without working example, hope it could be understood with provided code chunks.

    What I want to achieve is whener new point is added on a chart, scrollbar by default navigated to N last points and show them (N=5, 10,…). Here is main code which triggered when new item is added to code:

    
            private void UpdateChartsControls()
            {
             //NOTE, I omit some uninteresting stuff where
            // Axis X min and max values are calcualted based new data
    
    
                flexChartMain.AxisX.Max = max;
                flexChartMain.AxisX.Min = min;
                _aggregator.Source = _fdsi.Positions;
    
                //Debug.WriteLine($"Current max ole dt:{max}");
                //setup WHOLE range
                rangeSelectorChart.AxisX.Max = max;
                rangeSelectorChart.AxisX.Min = _fdsi.Positions.First().Date.ToOADate();
                 
    	  //you can ignore this if
                if (Settings.Default.ShowAggChart)
                {
                    ResetRangeSelector();
                    SetupRangeSelector();
                    if (Settings.Default.DoRangeTracking)
                    {
                        //setup visible(tracked) range
                        rangeSelectorCtrl.LowerValue = min;
                        rangeSelectorCtrl.UpperValue = max;
                    }
    
                    rangeSelectorCtrl.Refresh();//??
                }
                else
                {
                    SetupAxisXSelector();
                    _horizontalScrollbar.ValueChanged -= ScrollbarAxisXValueChanged;
                    Debug.WriteLine($"lw = {_horizontalScrollbar.LowerValue},uv = {_horizontalScrollbar.UpperValue}");
                    _horizontalScrollbar.LowerValue = min;
                    _horizontalScrollbar.UpperValue = max;
                   _horizontalScrollbar.ValueChanged += ScrollbarAxisXValueChanged;
                  
    		 _horizontalScrollbar.Tag = new Tuple<double, double>(min, max);
    
                }
    
            }
    
     private void SetupAxisXSelector()
            {
                if (Settings.Default.ShowAggChart)
                {
                    panel1.Visible = true;
                    SetupRangeSelector();
                }
                else
                {
                    panel1.Visible = false;
                    SetupAxisXScrollingSelector();
                }
            }
    
     private void SetupAxisXScrollingSelector()
            {
                if (_horizontalScrollbar != null)
                {
                    return;
                }
    
                _horizontalScrollbar = new AxisScrollbar(flexChartMain.AxisX);
                _horizontalScrollbar.ValueChanged += ScrollbarAxisXValueChanged;
            }
    
     private void ScrollbarAxisXValueChanged(object sender, EventArgs e)
            {
                if (_fdsi == null)
                {
                    return;
                }
    
                Debug.WriteLine($"_horizontalScrollbar.LowerValue={_horizontalScrollbar.LowerValue}");
                Debug.WriteLine($"_horizontalScrollbar.UpperValue={_horizontalScrollbar.UpperValue}");
                flexChartMain.AxisX.Min = _horizontalScrollbar.LowerValue;
                flexChartMain.AxisX.Max = _horizontalScrollbar.UpperValue;
    
            }
    
    

    The issue I have with this code is that for some reason scrollbar valuechanged event is called after UpdateChartsControls() and it overwrites my upper and lower value and shows scrollbar for it’s whole length instead of just needed length by N last points. In code above I unsubscribe from this event before changing lower and upper values, and then suscribe again, hoping that scrollbar would be rendered correctly but it is rendered for whole length of axis X.

    To illustrate further more what I need here is small chunk of code which is doing what I need but make scrollbar completely unusable:

    
    private void flexChartMain_Rendered(object sender, RenderEventArgs e)
            {
                if (!Settings.Default.ShowAggChart)
                {
                    if (_horizontalScrollbar.Tag is Tuple<double, double> tag)
                    {
                        _horizontalScrollbar.LowerValue = tag.Item1;
                        _horizontalScrollbar.UpperValue = tag.Item2;
                        
                        
                    }
                }
          }
    
    

    What i’m doing wrong? Why _horizontalScrollbar.ValueChanged triggered one more time with lower and upper values reseted by whole range of axis x?

    Thanks in advance.

    PS: I have to regimes of navigation on chart – additional chart (rangeSelectorChart) + range selector and simple mode with scrolling.

  • Posted 20 September 2022, 7:04 am EST

    Hi,

    JFYI, ValueChanged event will fire every time the values of AxisScrollBar changes. As we observed you are updating AxisX Min and Max values even though the AxisScrollBar is implemented on AxisX.

    There’s no need to update AxisX Min and Max vlaue. They can update according to UpperValue and LowerValue of AxisScrollBar. That’s why the AxisScrollBar’s thumb fully expands to the Scrollbar.

    Still, If you have issue then please provide a small stripped sample or you can update to the attached sample to replicate the issue. So, that we can assist you accordingly.

    Please refer the attached sample for the same :

    FlexChartAxisScrollBar.zip

    Regards,

    Nitin

  • Posted 20 September 2022, 2:40 pm EST

  • Posted 20 September 2022, 2:40 pm EST

    Hi, thank you very much again.

    Here is code. Please, note I use C1 for fw 4.5.2 and my version of C1 is 4.5.20221.557

    So, as you can see after I add new point via btn click, I try to setup visibility of last N points (N can be edited by numericbox). No success, show whole axis x, but when I change last N visible points, it behaves correctly, as I expect. So, I have two methods which have minor change and behaves completely different:

    
      public void AddNewPosition(DataPoint dataPoint)
            {
                if (dataPoint == null)
                {
                    throw new ArgumentNullException(nameof(dataPoint));
                }
    
                if (InvokeRequired)
                {
                    Invoke(new Action(() => AddNewPosition(dataPoint)));
                    return;
                }
    
              points.Add(dataPoint); //<-- this line seems to make difference
                UpdateChartsControls();
            }
    
    
            private void numericUpDown1_ValueChanged(object sender, EventArgs e)
            {
               UpdateChartsControls();
            }
    
    

    What makes this difference in behaviour? Also I’ve notices that AddNewPosition code causes rerendering which triggers method ScrollbarAxisXValueChanged. Maybe there is some issue with databinding or data source?

    Also, please give advice on code, mainly on UpdateChartsControls method, maybe I do some redundant call like rebind, and so on and so forrh.

    Thanks in advance.

    https://gccontent.blob.core.windows.net/forum-uploads/file-3fa9d718-e4ef-4efd-a69c-8cafddea060d.zip

  • Posted 21 September 2022, 1:18 am EST

    Hi,

    Thanks for the modified sample. We can replicate the issue at our end i.e., the UpperValue and LowerValue is not reflecting in chart while adding Points more than 5.

    The best approach to reflect the changed LowerValue and UpperValue is to handle with Rendering event.

    
    private void FlexChart1_Rendering(object sender, RenderEventArgs e)
    {
        _horizontalScrollbar.LowerValue = min;
        _horizontalScrollbar.UpperValue = max;
    }
    
    

    Now we can render the last N points(value from numeric box).

    Please refer the attached sample for the same : FlexChartAxisScrollBar_Mod.zip

    Yes, this is true. That the AddNewPosition will fire Rendering event(which is fired when flexchart element renders or changes. In the case of AddNewPosition, the new symbol point is adding and that’s why the Rendering event is firing.

    Best Regards,

    Nitin

  • Posted 21 September 2022, 8:54 am EST

    Hi.

    Again, thank you for reply. That is what I was guessing and wanted to avoid – introduce another local state, namely min and max fields. Next question – is it possbile some how to separate this two processes, namely adding and rendering and then updating? I mean, make it not render after UpdateChartsControls in AddNewPosition method. Simple state machine – add new values to ds, render and then update. Not to delay render when whole method AddNewPosition is executed but rather force to render after addition. Is it possible?

    Thanks in advance.

    b]Update[/b]: I’ve looked at your solution and test it, it doesn’t work at all, that what I’ve did with Tag property (see code above), scrollbar is completely unsuable in your code. I guess it could be modified with Tag, but I need guarantee that it will be called only once after method called.

    Update2:

    My apporach with patching UpdateChartsControls , namely setting tag

    flexChart1.Tag = new Tuple<double, double>(min, max);

    and using

    private void FlexChart1_Rendering(object sender, RenderEventArgs e)

    {

    if (flexChart1.Tag is Tuple<double, double> tup)

    {

    _horizontalScrollbar.LowerValue = tup.Item1;

    _horizontalScrollbar.UpperValue = tup.Item2;

    flexChart1.Tag = null;

    }

    }

    doesn’t work with 3 times rendering method called. Even this doesn’t work

    if (flexChart1.Tag is Tuple<double, double> tup)

    {

    _horizontalScrollbar.ValueChanged -= ScrollbarAxisXValueChanged;

    _horizontalScrollbar.LowerValue = tup.Item1;

    _horizontalScrollbar.UpperValue = tup.Item2;

    _horizontalScrollbar.ValueChanged += ScrollbarAxisXValueChanged;

    flexChart1.Tag = null;

    }

  • Posted 22 September 2022, 6:18 am EST - Updated 3 October 2022, 10:12 pm EST

    Hi,

    1. It can’t be possible to invoke render before Chart UpdateChartsControls. Rendering will fire on every UI changes for Flexchart. So, after AddNewPosition it willl fire.

    2. Try the solution that we have provided previously. It’s working and the Scrollbar updates on every added points which shows the last N points. (see FlexChartAxisScroll.gif)

    The above gif shows the last 5 points which is added to the FlexChart.

    Best Regards,

    Nitin

  • Posted 22 September 2022, 11:02 am EST

    Hi, Nitin! Thank you for reply again.

    Sorry, maybe I was not so clear in my comments above, but I need fully functional scrollbar. Put it simply, what I need:

    1. there is option in program to track last N points (call it window or range), namely when new points is added and point.Count > N, show N last points;
    2. what I have currently with scrollbar is either it shows whole range(whole points) or

      it is sticked within interval of N last points. After you add 10 points in code above try to use scrollbar , it won’t even move because
    private void FlexChart1_Rendering(object sender, RenderEventArgs e)
    {
        _horizontalScrollbar.LowerValue = min;
        _horizontalScrollbar.UpperValue = max;
    }
    
    

    and as a result I lost functionality of scrollbar completely. Why do I need it at all if I can directly setup flexchart min and max? In your gif above it works correct only for showing last N poinst, great, but try to move scrollabr to navigate to other chart region or to show whole chart. You can’t and that is the problem.

    Does it make sense now?

  • Posted 22 September 2022, 12:37 pm EST

    FYI, this seems to be what I need:

    
     public async void AddNewPosition(DataPoint dataPoint)
            {
                if (dataPoint == null)
                {
                    throw new ArgumentNullException(nameof(dataPoint));
                }
    
                if (InvokeRequired)
                {
                    Invoke(new Action(() => AddNewPosition(dataPoint)));
                    return;
                }
    
                points.Add(dataPoint);
                await Task.Delay(300);
                UpdateChartsControls();
            }
    
    

    The thing is, can it be more smooth because for some small time interval I show all points (whole range) and then select last N points, need to avoid this ugly flickering? Can make small delay (1 msec) but I’m afraid that behavoiur would be same as no delay at all, namely sequential execution.

  • Posted 23 September 2022, 7:57 am EST

    Anyone?

  • Posted 23 September 2022, 8:02 am EST

    Hi,

    Apologize for any inconvenience.

    We didn’t realized that the scrollbar is not movable with our solution.

    This is because of Rendering event. While moving Scrollbar, Rendering event fires and the UpperValue and Lowervalue resets.

    You need to set UpperValue and LowerValue after adding ChartDataPoint with a small amount of delay like you have mentioned. There’ll be no issue having less amount of delay. We need to wait till Axis render on FlexChart. So, that we can adjust the LowerValue and UpperValue of AxisScrollBar.

    Regards,

    Nitin

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels