Axis.VisibleRange - a Note about Dependency Property Precedence
Posted by Andrew BT on 05 February 2019 04:00 PM
|
|
A Note about DependencyProperty PrecedenceAxisBase.VisibleRange is a DependencyProperty, it is therefore subject to Dependency Property Precedence in WPF. See the MSDN Documentation for more details.
Internally, SciChart sets the AxisBase.VisibleRange property using the Local Value precedence in some places. We must do this as ChartModifiers, and AutoRange need to update the AxisBase.VisibleRange. This means that in some cases, style setters and templated properties setting Axis.VisibleRange will not appear to work. For this reason we recommend that any bindings to VisibleRange are a TwoWay binding to a ViewModel property: e.g. <!-- Assumes a ViewModel property called AxisVisibleRange --> <!-- TwoWay Binding is required to avoid DependencyProperty Precedence issues --> <s:NumericAxis VisibleRange="{Binding AxisVisibleRange, Mode=TwoWay}"/> Triggers and DependencyProperty PrecedenceIn some cases, Triggers will also not work on the AxisBase.VisibleRange, e.g. the following code will fail: <Style x:Key="YAxisStyle" TargetType="s:NumericAxis"> <Setter Property="VisibleRange" Value="0, 5"></Setter> <Setter Property="AutoRange" Value="Never"></Setter> <Style.Triggers> <Trigger Property="Tag" Value="1"> <!-- Removing AutoRange=Always setter and uncommenting this next VisibleRange setter shows how the timer changes states --> <!--<Setter Property="VisibleRange" Value="0, 7"></Setter>--> <Setter Property="AutoRange" Value="Always"></Setter> </Trigger> <Trigger Property="Tag" Value="2"> <Setter Property="AutoRange" Value="Never"></Setter> <Setter Property="VisibleRange" Value="0, 10"></Setter> </Trigger> </Style.Triggers> </Style> ... <s:NumericAxis Style="{StaticResource YAxisStyle}"/> In the above code, which was submitted to us by a customer of SciChart, the AxisBase.AutoRange property is used to switch between AutoRange.Always and AutoRange.Never and a predefined range. This code does not work, as once AutoRange.Always is set on the Axis, and SciChart then sets the AxisBase.VisibleRange property via local value precedence, and the trigger (with lower precedence) will not work. We suggest instead one of the following solutions instead: Binding BOTH to AutoRange and VisibleRange in a ViewModel The following method uses a TwoWay binding for the VisibleRange property, and will allow updating of both AutoRange and VisibleRange from the ViewModel. <Style x:Key="YAxisStyle" TargetType="s:NumericAxis"> <Setter Property="VisibleRange" Value="{Binding ViewmodelVisibleRange, Mode=TwoWay}"></Setter> <Setter Property="AutoRange" Value="{Binding ViewModelAutoRange, Mode=TwoWay}"></Setter> </Style> ... <s:NumericAxis Style="{StaticResource YAxisStyle}"/> ... // then in ViewModel public DoubleRange VisibleRange { get { return _range; } set { _range = value; OnPropertyChanged("VisibleRange"); } } public AutoRange AutoRange { get { return _autoRange; } set { _autoRange = value; OnPropertyChanged("AutoRange"); } }
Using an Animation to set values in a Trigger Another idea is to use ObjectAnimationUsingKeyFrames with 0 duration to set values in a trigger. Animations have the highest precedence for a DependencyProperty and always trump local values.
ItemTemplates and DependencyProperty PrecedenceIn some cases VisibleRange bindings inside a style, inside an ItemTemplate will have a lower DependencyProperty Precedence than the local value set by SciChart AutoRange and modifiers. The following code is taken from our Create Multi Pane Stock Charts demo: <!-- Databinds a SciChartGroup to a list of ChartPaneViewModels --> <!-- Child chart panes are generated using the ItemTemplate below --> <s:SciChartGroup Grid.Row="1" ItemsSource="{Binding ChartPaneViewModels}" s:ThemeManager.Theme="{Binding ElementName=ThemeCombo, Path=SelectedItem}" ItemContainerStyle="{StaticResource ChartPaneStyle}"> <s:SciChartGroup.ItemTemplate> <DataTemplate> <Grid> <!-- Axis Properties, like s:StockChartXAxis.VisibleRange are databound to CreateMultiPaneStockChartsViewModel.XVisibleRange --> <s:SciStockChart x:Name="PART_ChartPaneView" ...> <!-- Override any properties of the built-in CategoryDateTimeAxis --> <s:SciStockChart.XAxisStyle> <Style TargetType="s:CategoryDateTimeAxis"> ... <Setter Property="VisibleRange" Value="{Binding ParentViewModel.XVisibleRange, Mode=TwoWay}"/> ... </Style> </s:SciStockChart.XAxisStyle> ... </s:SciStockChart> ... </Grid> <DataTemplate> </s:SciChartGroup.ItemTemplate> </s:SciChartGroup>
The above code works because of the TwoWay binding between VisibleRange and a common ViewModel property, however without the TwoWay binding it would not work, because bindings inside a template a at a lower precedence than local values set. If you have any problems with VisibleRange and DependencyProperty PrecedenceContact us! Give us your code sample and what you expect to happen, and we will modify this article and post a solution for you.
| |
|