How to plot placeholder series that shows X axis labels

15 posts, 0 answers
  1. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 13 Dec 2012 Link to this post

    Hi Petar,  as we have discussed previously, my app receives data from remote sources and I add it to a chart in the elapsed event of a timer.  The timer that updates the chart runs continuously however there are often periods of time when no data is received.  For those periods I want to display the X axis label (i.e. the time) and a blank space where the bar should be.  So, for long periods of time where no data is received the user should simply see the x axis labels scrolling to the left (no bars) as the chart is updated.  Please note in my app that there are no series initially defined for my chart.  The reason for that is that the series are linked to a property of the data and until I have data to display I don’t know what series to display.

    Having said that, there are two  issues which I would like to bring to your attention and attempt to resolve:
    1.)  When the application is first loaded there is no data and no series as described above.  I add a series with Y values = 0 and X values containing time periods in the past (the labels on the X axis are time stamps).  The purpose of adding this series is to  overcome issues with bar width that I have asked about in prior posts, and also to act as a placeholder for time periods (bars) where there is no data.  My intent is that the X axis labels should ALWAYS appear on the chart, but the bar fragments for this placeholder series should never appear on the chart (the Y values are always zero).  The problem is that when there is no data there is no Y axis so the placeholder series is plotted at the full height of the chart even though the values are zero.  How do I suppress plotting the bars for this series but keep the X axis labels?  Ideally I would like a Y axis scale to always appear on the chart.  If I could initially set that scale to have a max of, say, 1 that would cause the zero value placeholder series to have no height which would work just fine.

    2.) When all data scrolls off the left side of the chart, new bars are not plotted when data is received.  This issue can be reproduced as follows:

    Load the attached app and click Start Generating Data.

    Wait until a few bars are generated then click Stop Generating Data.
    Wait until all bars have scrolled off the left side of the chart. Notice that the placeholder series is plotted at full height (this is the issue described above).
    Click Start Generating Data.  Notice that no bars are plotted.

    Repeat the above steps but do not allow all data to scroll off the left side of the chart.  When you click Start Generating Data again, data will plot as expected.

    I found that adding a placeholder row in my data collection will work around this issue.  Uncomment the following code in the AddLoadStatistic method.  However I am not certain this is a fix, or perhaps I am doing something else that’s wrong that is causing this issue (???).

    if (LoadSources.Count > 0)
                {
                    foreach (System.Collections.DictionaryEntry key in LoadSources)
                        LoadStatistics.Add(new LoadStatistic { PeriodEnding = LoadIntervalEndTime, Source = key.Key.ToString() });
                }
                else

  2. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 13 Dec 2012 Link to this post

    Need an email address to send a zip file please.
  3. UI for WPF is Visual Studio 2017 Ready
  4. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 17 Dec 2012 Link to this post

    Are you guys working this week?  I'v got code waiting to go to prod. 

    Thanks
  5. Petar Kirov
    Admin
    Petar Kirov avatar
    425 posts

    Posted 18 Dec 2012 Link to this post

    Hi Sam,

    Please excuse me for the delayed answer. 

    1. I have attached a modified version of your project to demonstrate my idea. Basically I moved the initial creation of the place holder series in a new method - AddTransparentSeries, which is a modified version of your AddSeries method. There I changed the series type from Bar to Line, set their Stroke to Transparent and removed their CombineMode setting. I hope this satisfies your requirements. 

    2. As far as I can see the cause for the second problem is in your code and not in the ChartView control. I came to that conclusion by attaching to the CollectionChanged event of the ItemsSource of one of your series.

    The CollectionChanged is raised as expected when when data is generated (i.e. "Start Generating Data" is pressed). However when I stop the data generation and wait long enough for the bars to come out of scope and then restart the data generation, the CollectionChanged is no longer raised, which means that no new data points are added. The ChartView relies on that event to refresh its series.

    I will get back to you with a simple project, demonstrating a better approach to your scenario using our RadChartView control.

    Regards,
    Petar Kirov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  6. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 18 Dec 2012 Link to this post

    Hi Petar, thank you for respose.  With regard to item 1, I'm still testing but your solution looks promising.  Thank you!
    For 2.) please use RadCartesianChart if you show a solution as that is the control I'm using in my project.

    Thanks,

    Sam
  7. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 18 Dec 2012 Link to this post

    >>Repeat the above steps but do not allow all data to scroll off the left side of the chart.  When you click Start Generating Data again, data will plot as expected.

    Petar, I'm not sure if you tested the above - Please note the problem I describe is only exibited if all the data scrolls off the chart.  If any bars remain on the chart it works fine. 
  8. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 19 Dec 2012 Link to this post

    Petar,  Please look at this code I implemented in the AddLoadStatistic method in the code I provided:

    if (LoadSources.Count > 0)
    {
     foreach (System.Collections.DictionaryEntry key in LoadSources)
      LoadStatistics.Add(new LoadStatistic { PeriodEnding = LoadIntervalEndTime, Source = key.Key.ToString() });
    }

    I implmented this code as a workaround for the problem where new bars do not appear if all bars scroll off the screen.  I would be OK with just leaving this code as-is, however this code has a bad side effect.  When all the bars scroll off the screen, all series are plotted at full height, just like the condition you fixed with AddTransparentSeries.  I would like to omit this code if possible if there is a bug in my code that is causing this kindly bring it to my attention as I am unable to figure it out.  I already tried setting the Y value of the transparent series to 1 to flatten the other series but it does not work.

    Thanks,

    Sam

  9. Petar Kirov
    Admin
    Petar Kirov avatar
    425 posts

    Posted 21 Dec 2012 Link to this post

    Hi Sam,

    I have attached the live data demo project using RadCartesianChart as promised. 

    I can confirm that I tested all of the scenarios listed in your first post - the issue with data not being added is only apparent if you wait till all of the already generated data scrolls out of the plot area. As I said previously, the issue seams to be caused by the way you are using the control. 

    That said, I would recommend implementing the approach explained below in your project.

    Some of the important things to note about it are:
    • I have used the MVVM design pattern to bind the ItemsSources of the series and the range of the horizontal date time axis to properties of the ViewModel. That way the code is easier to track and maintain. 
    • The two chart series (placeholder series and actual data series) objects are defined in XAML (to enable binding) and are alive during the whole application lifetime. This is not an issue even if new data does not arrive at regular intervals. In the Tick event event handler of the ViewModel timer, you can ask your data source if there is new data. If there is - add it to the ViewModel.Data collection, else wait for the next Timer.Tick.
    • By keeping the horizontal axis in a fixed range, it is ensured that a fixed number of datapoints is visible at all time. That way the bars of the BarSeries will have a fixed width. If you want the bars to align with the axis ticks (timeslots) you can keep the axis.MajorStep the same as the timer.Interval.
    • The date time axis range (i.e. the difference between axis.Maximum and axis.Minimum) can be controlled through the ViewModel.AxisRange property, specified in seconds and the refresh rate (timer.Interval) - through ViewModel.Delay.

    All the best,
    Petar Kirov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  10. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 24 Dec 2012 Link to this post

    Hi Petar, thank you for your patience and continued support. I appreciate the effort you have put into resolving these issues. However I do not understand how the application you gave me addresses the problem I requested help for.  The application you gave me does not utilize QueryableCollectionView, it does not illustrate stacked bars, and it does not provide for adding series in code (a requirement I stated in my initial post and also in comments in the code I provided).  Further, your example assumes data is added to the chart as bars scroll, whereas in my app I made an effort to exemplify that data is added to the chart at intervals that are unrelated to time periods shown on the chart. So, while I may be using the telerik controls incorrectly (and you have not convinced me that I am), I am using them to meet certain business rquirements and those requirements cannot be disregarded in the name of making the control work.

    I attempted to modify your example to suite my need and I'm right back where I started with the same problem I documented in earlier posts.  I cannot afford to spend another day hunting through an example hoping to find why the control does not work.  Please provide specific instruction on how to resolve the problem I documented while implementing the requirements of the example code I origianally sent you. Please note that code is a fragemnt of a much larger program.  The example was written to simplify and illustrate certain issues and for that reason does not implement MVVM.  The program it models does implement MVVM.  Note that MVVM is a good practice but is not required for WPF applications.

    Again - please be specific and state the required usage of the control in the code I originally sent you as it contains the business requirements I need to implement.

    Thanks,

    Sam

     

  11. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 26 Dec 2012 Link to this post

    Hi Sam,

    From your correspondence with Petar Kirov, I can see that the first issue has been resolved (using the AddTransparentSeries method). Please correct me if I am wrong.

    About the second issue you have described (that the chart does not refresh after all visible bars has scrolled to the left) - I think that Petar Kirov has addressed this as well.

    "2. As far as I can see the cause for the second problem is in your code and not in the ChartView control. I came to that conclusion by attaching to the CollectionChanged event of the ItemsSource of one of your series."

    I have reattached one of the project that he had attached, just to avoid the confusion about which project I am talking about. I will be talking about the project I have attached in this post.

    There is an event handler called observableCollection_CollectionChanged. This is the handler to the CollectionChanged event of the itemsSource that you are passing to the chart (in the AddSeries method). I debugged by inserting a break point in the observableCollection_CollectionChanged handler. This handler is executed when bars are added to the chart. However when all the bars scroll off the screen, this handler is no longer executed. The RadCartesianChart also has subscribed to this event and since the event is not raised - the chart does not know that it should update. The event not being raised seems to be a flaw in your application and not in the RadCartesianChart.

    To reproduce this:
    1. Run the attached app.
    2. Insert a break point in the observableCollection_CollectionChanged handler.
    3. Click the Start Generating Data button
    4. Note that the break point is being hit and the chart is properly updated
    5. Press the Start Generating Data button again
      This causes the present bars to slide, but no new bars are generated.
    6. Wait for all bars to scroll off the screen.
    Note that while waiting for this to happen, the break point is still being hit.
    7. See that after all bars have scrolled of the screen - the break point is no longer hit.

    This results in the chart not knowing it should update, hence this inadequate behavior. Do try this and see if you can find the reason for this behavior.

    Do let me know if I have not addressed any of the issues that concern you. 

    Note: RadCartesianChart is a part of the ChartView set, which also contains the ChartDataSource, RadPieChart and others.

    Kind regards,
    Petar Marchev
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  12. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 27 Dec 2012 Link to this post

    Hello Petar & Petar,  Thank you for your ananlysis and your response.

    >> "The RadCartesianChart also has subscribed to this event and since the event is not raised - the chart does not know that it should update."

    So the question is "Why is the event not raised?"  We know the event IS raised initially, and you already confirmed that.  However, nowhere in my code do I handle, or un-handle, the collection changed event of the collection that serves as the itemssource for a given series.  If you beleive that statement is incorrect, kindly paste into your response the specific lines of code that cause the issue or that should prevent it.

    Note that any series added to the chart, and its ItemsSource, are valid and in-scope as long as the series is part of the series collection of the chart.  To test this I added collection changed event handlers to my underlying collection (LoadStatistics) and to the Telerik grouping control (GroupedData).  These collections always raise their collection changed events when they are modified just as they should (irrespective of the bars on the chart).  In the handler for LoadStatistics I look at the ItemsSource for the first series on the chart.  It is never null, and it should never be null as it is just a pointer to LoadSeries collection.  So, for some reason, the collection remains in scope but its Collection changed event is not raised.

    Petar has added to my code these lines:
    var observableCollection = itemsSource as INotifyCollectionChanged;
    observableCollection.CollectionChanged += observableCollection_CollectionChanged;

    Nowhere in the code did he add any lines to un-handle the event.  Or, if I have missed the code he added, please include it in your response.  So there is no reason for the observableCollection_CollectionChanged method to NOT fire when the underlying collection is changed, correct??  So here we have an example where a developer has explictly added a handler to event - but for reasons unknown to the develper his handler has ceased to fire when the event occurs.  Please note we are not handling an event related to the chart - we are handling an event related to a collection.  The fact that bars exist on the chart or not is irrelevant and the existance and validity of Petar's event handler should not be tied to that condition.  

    Dont you think it is a bit strange that the collection changed event stops firing at the same time bars for a given series scroll off the chart??  Do you think the chart control can be the one who is setting the event to null so no events are raised??? I'm just speculating of course but that certainly seems to be reasonable, dont you think?  The fact that no bars are added to the chart is in my mind an error conditon.  The fact that Petar's event handler is not fired appears to confirm that the chart seems to be un-handling the series collection changed event not only for itself, but also for other subscribers (an even worse error!!).

    >> "Do let me know if I have not addressed any of the issues that concern you."
    No, you have graciously assisted me in locating a problem but I have no idea how to fix it.  I do not wire the charts event handler to the changed event of my collection, nor do I un-wire it.  I have no idea when, where, or how to fix this issue.  Please reccomend a fix that also includes the business objectives I need to implement.  This may very well be my bug but I have no idea how to fix it.  Happy New Year and thanks for your help.

     

     

  13. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 01 Jan 2013 Link to this post

    Hi Sam,

    Indeed we have not pin-pointed the exact reason for this incorrect behavior so far, and I am sorry if this is stalling your project's development. With my previous post I wanted to state that the bug is not in the RadChartView control and I hoped that you will quickly identify where the problem might be. After a more thorough examination of your code I have found the reason for this issue.

    You are using the QCV (QueryableCollectionView) with GroupDescriptors. As a result you have three groups in the qcv.Groups collection. However, after some time when data has stopped coming, there is only 1 group in that collection, the "@@@" group. At this moment the "STP" and "AE" groups no longer exist in the qcv.Groups collection. However, these are the two items sources you have passed to the chart.

    Now when you add new items to your business collection, new groups are created and added to the qcv.Groups collection. The chart is still using the old ones, where the qcv is using the new ones. 

    Do let me know if I explained it well enough and if we can assist you further.

    Kind regards,
    Petar Marchev
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  14. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 03 Jan 2013 Link to this post

    Thank you Petar.  I reset the ItemsSource on each series and it works.  However, the series does not update again until a new x axis value is added.  I dont have the time to document it sorry.  I'm sure you have already implemented a similar fix in the example code I sent, you should see the same behavior.
  15. Petar Marchev
    Admin
    Petar Marchev avatar
    968 posts

    Posted 07 Jan 2013 Link to this post

    Hello Sam,

    I did not fully understand you. Have you fixed this issue or do you need further assistance?

    All the best,
    Petar Marchev
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  16. Sam
    Sam avatar
    18 posts
    Member since:
    Nov 2012

    Posted 07 Jan 2013 Link to this post

    It works.

    But I found a new issue.  I'll write up a new thread when I have some time.

    Thanks again,

    Sam
Back to Top
UI for WPF is Visual Studio 2017 Ready