I have a XamDataChart that I created that receives live data every second. I needed the ability to allow the user to pan and scroll the view and when the user is not looking at the right axis I needed the view to be static but still indicate that data was flowing in. To accomplish this I had to check see if the user was looking at the far right by adding the ActualWindowPositionHorizontal and ActualWindowScaleHorizontal together to see if it equals 1. If not then the user either panned or zoomed and therefor I need to keep the view static. To accomplish that I handle the OnWindowRectChanged event and I shift WindowPositionHorizontal 1 second to the left and shrink the WindowScaleHorizontal to the appropriate amount to maintain the exact position and size until the user resets the view to the far right. I have this working,however, now I have 3 XamDataCharts linked via the SyncManager. I have all 3 charts' series' xaxes' Minimum and Maximum vales bound to the same viewmodel properties as I did in the control with only a single datachart. What I find is that as soon as one fires the OnWindowRectChanged is fired the others fire as well and this causes a recursion error and the app crashes. What I need to know is how am I supposed to manually update WindowScaleHorizontal and WindowPositionHorizontal properties on synced datacharts? Is there a way to make the user's view "fixed" when zoomed/panned without modifying the position and scale each time the datasource gets more data added to it and the xaxes' MaximumValue is increased? Should only one of the charts xaxes' MaximumValues be bound to the viewmodel since they are synced?
I am attempting to come up with a sample to reproduce my problem but the charts have a lot of companion code that is making it time consuming.
Please let me know if you need more detail.
Hi Mike,
It is expected that the other charts would fire the WindowRectChanged since the panning/zooming is linked. What is the code that you are running inside the WindowRectChanged event? I have a sample up with 4 synchronized charts and "live" data streaming in every second.(I'm just generating a random data point and adding it to the data source every second)
Also from my understanding of your requirement, the data chart should already be able to do that by default. That is, keeping the view static while data flows in. As an example, in my sample I adjust the horizontal zoombar scale to zoom in horizontally and then pan the chart all the way to the right. The view will stay there and you can see the data flow in from the right, moving to the left. And since all my charts are synchronized, they all perform the same way. I've attached the sample to this post. Is this not what you were looking for?
This is very close but where the tricky part comes in is when your sample is panned away from the far right the "data" must appear static. This means that the WindowHorizontalPosition needs to move to the left at the same speed that data is coming in. Also, your scale is static and I need the scale to adjust so that the amount of viewable time is always the same. As more data comes in the scale has to adjust to compensate an make the view appear to always show the same amount of time. Your sample is showing more and more data in the view as more data arrives.
Does that make sense?
Thanks,Mike
Yep, that makes sense. I misunderstood what you were looking for but now I get it. I'll just reiterate to confirm.
You want the view to follow the data so that the chart appears static while it's NOT up against the very right side. You also want the same amount of time viewable at all times and you do this by updating the WindowHorizontalScale property.
With regards to adjusting the scale to keep the same amount of viewable time the same, is this where you are modifying the minimum and maximum values for the XAxis to do this?
I'll modify my sample further to incorporate this new information. I'll get back to you tomorrow.
Do you still require assistance on this issue? Can you modify the sample I sent earlier to include the behavior you currently have? I can then work off of this.
I'm having difficulties getting this working the way you want it. Can you modify the sample I sent earlier to include the behavior you currently have?
"Perhaps I do not need to update the position and zoom if the user is on the far right?"
This is correct. If you place the window position to the far right and leave it there, you will see the data flow in from right to left which is what you want in that case. You don't need keep updating the position/scale in that specific case.
As far as a better event for detecting zoom or pan, either WindowRectChanged or the zoombar event XamZoombar.ZoomChanged are you're only choices. ZoomChanged is called anytime the actual zoombar at the bottom of the chart is modified. This includes resizing the thumb or dragging it to a different location along the zoombar. The values are placed in the XamZoombar.Range property and the range just marks off the left-most/right-most ends of the thumb from 0 to 1. I don't see how using this event could cause you problems though as the event doesn't care whether the zoombar was panned or zoomed. It's all about the size and position of the thumb that matters.
You are correct. Those are my goals. The viewable time needs to be static until the user changes it anyway.
When data first comes in I set the MinimumValue and every second I add 1 to the MaximumValue of my viewmodel and all the xaxes are bound to these two properties. Then every second I update the WindowHorizontalScale and WindowPositionHorizontal like this:
if (Zoomed) { // shift the position to the left by the size of the added time WindowPositionHorizontal = WindowPositionHorizontal - ((1 / span) * WindowPositionHorizontal);
// reduce the size of the zoom to be the same proportion after the added time WindowScaleHorizontal = (WindowScaleHorizontal * (span - 1)) / span; } else { // When the user has not zoomed or scrolled the window we need to keep the view // set to the far right to see the most recent data and set the zoom so that only // the selected number of seconds is showing WindowScaleHorizontal = ViewSizeinSeconds / span; WindowPositionHorizontal = 1 - WindowScaleHorizontal; }
This does produce the functionality I want if I only have a single graph. When multiple graphs are involved I run into recursion problems. The reason for this is that I need to determine when a user has scrolled or zoomed and right now I am attempting to use the OnWindowRectChanged of the graph. THis fires all the time and I think I have it barely wired up in the single graph mode. Is there a better event to use to detect when a user has completed a zoom or pan? I am still experimenting and I found that I can handle the XamDataChart.HorizontalZoomBar.Zoomed event but it appears to send the change in position and scale in 2 separate events which is causing difficulties. Perhaps I do not need to update the position and zoom if the user is on the far right?