02-08-2021 07:27 AM
Hi,
I am using an IntensityGraph with a custom time Axis from M21259, however I have troubles getting the range binding to work properly. I am using InteractionMode="EditRange", but when range is changed I get no call to the binding method (range is changed by editing directly on time axis during runtime). All is configured in xaml using: <local:CustomAxis StartTime ="{Binding WaterfallStartTime}" Range="{Binding WaterFallRange}" InteractionMode="EditRange" Adjuster="ContinuousChart" >. If I instead add a callback, i.e. RangeChanged="CustomAxis_RangeChanged" this is working, but since I use MVVM this is not preferred. Am I doing something wrong? I can provide a simple running code if that helps. Thanks!
Brg.
Oddvar
Solved! Go to Solution.
02-10-2021 10:36 AM
In this case, you need to explicitly tell WPF you want a two-way binding: Range="{Binding WaterFallRange, Mode=TwoWay}"
02-11-2021 10:35 AM
Hi,
I am afraid I already tried that without success. Added a simple running example, hope this helps. Try to change the end time of the time axis, I can't get it to call the Range binding. Another issue I don't understand is that if you first try to edit the start time of the time axis this doesn't work, it is set back to 00:00 again. You need to edit end time before start time. Why? Is it some sort of initialization issue?
Brg.
Oddvar
02-11-2021 12:59 PM
Thank you for the simple code example! Running in debug, I see this error in the Output window:
System.Windows.Data Error: 1 : Cannot create default converter to perform 'two-way' conversions between types 'NationalInstruments.Controls.Range`1[System.DateTime]' and 'NationalInstruments.Controls.Range`1[System.Double]'.
The custom axis is designed to display values as time by telling the graph that the data source uses DateTime
values, but the actual data type of the range is still double
, not DateTime
. The binding either needs a Range<double>
property to act as the source, or a converter to translate between double
data and DateTime
display types (similar to the logic in the custom formatter).
As for the issues with range editing, this stems from the how DateTime
parses time-only value. Given a string with just a time (e.g. "12:34:56"
), parse will return DateTime.Now.Date
plus that time. But the custom axis is configured with DateTime.MinValue
as the start, so the returned parse value will be much larger for whatever time is entered, and the axis will reject attempts to edit the minimum to be above the maximum.
To fix this, you can set the EditRangeValueFormatter
to a value that includes both the date and the time:
<local:CustomAxis.MajorDivisions>
<ni:RangeLabeledDivisions>
<ni:GeneralValueFormatter Format="HH:mm:ss" />
<ni:RangeLabeledDivisions.EditRangeValueFormatter>
<ni:GeneralValueFormatter Format="G" />
</ni:RangeLabeledDivisions.EditRangeValueFormatter>
</ni:RangeLabeledDivisions>
</local:CustomAxis.MajorDivisions>
Or you can create a custom formatter with additional logic to use the existing date value and add just the newly parsed time value, to keep the same text when displaying or editing an axis division.
Aside: I see you created a dependency property for StartTime
on the custom axis. Just two notes: as the dependency property type is DateTime
, the accessor can also be updated to the non-nullable type to match; and using the dependency property change callback is the appropriate way to do invalidation, so no need to also invalidate in the property setter.
public DateTime StartTime
{
get { return (DateTime)GetValue(StartTimeProperty); }
set { SetValue(StartTimeProperty, value); }
}
02-12-2021 09:02 AM
Thanks for this Paul! I didn't notice that I could see the error in the output window! Changed to double and added a converter and now it works perfectly.
Regarding the issues with range editing, this explains why it works when I initialize the range with values :-). Thanks for explaining!
Thanks for the information regarding the StartTime, I see that this of course is covered by the dependency property change callback. Copied this from an example where dependency was not used and didn't notice this.
Brg.
Oddvar