Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Bind multiplotcursor value

Solved!
Go to solution

Hi,

 

I'm trying to update the axis value of the multi-plot cursor using binding in XAML:

 

<ni:Graph.Children>
<ni:MultiPlotCursor Name="cursor" TargetBrush="DarkGray" SnapToData="True" AxisValue="{Binding Player.PlayPosition, Mode=OneWay}"/>
</ni:Graph.Children>

 

When I execute the code the cursor position never changes, however when I simply bind to a text box I can see the value changes.  In the editor I can set the axis value to a static value and I can see the change occur.

 

So, I'm a little confused why the position doesn't change even though the bound value changes.  What am I missing?

 

Thanks.

0 Kudos
Message 1 of 7
(7,013 Views)
Solution
Accepted by topic author Qbits*

The MultiPlotCursor updates the AxisValue property when it receives new data or is moved in the graph. When WPF sees the property assignment, it ends up removing the one-way binding in favor of the local value.

 

To bind to the value property of a graph cursor, use a two-way binding. In this case, WPF sees the assignment and applies it back to the source property, rather than removing the binding.

~ Paul H
0 Kudos
Message 2 of 7
(7,001 Views)

Thanks. I assumed the default binding was two-way.   When it wasn't updating the value like the text box (using the same binding) I thought there was something wrong so I tried one-way.  

0 Kudos
Message 3 of 7
(6,991 Views)

I am having a similar problem binding to a multipointcursor AxisValue. Basically the binding is not working at all! I was wondering if this may be because my graph is in a datatemplate populated by an itemscontrol.

 

My datatemplate looks like this:

 

        <DataTemplate DataType="{x:Type local:PlotData}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition MaxWidth="200"/>
                </Grid.ColumnDefinitions>
                <ni:graph Grid.Column="0" DataSource="{Binding XYData}" Width="Auto" Height="Auto">
                    <ni:graph.Children>
                        <ni:MultiPlotCursor Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ShowMarkers, Converter={StaticResource markerVisConverter}}" AxisValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.MarkerXValue, Mode=TwoWay}"/>
                    </ni:graph.Children>
                </ni:graph>
                <ni:Legend Grid.Column="1" ItemsSource="{Binding DisplayNames}" Width="175" MaxHeight="160"/>
             </Grid>
        </DataTemplate>

 

MarkerXValue is a property of my viewmodel (data context of my window) of type double.

 

However many graphs i plot I want to keep a single XValue for all the markers so they all line up. The binding on the visibility of the cursor works fine - why is it the binding on the AxisValue fails (and appears to not even fire when a dummy converter is put in place and the cursor is moved)?

0 Kudos
Message 4 of 7
(6,825 Views)

It appears this is an issue with the way the multi-plot cursor updates the AxisValue property. While the data template is being constructed, the Window ancestor is not available, so the binding fails to evaluate. When the cursor updates the property value, the binding system discards the binding, rather than waiting until the ancestor can be resolved.


As a workaround, you can use a custom intermediary object to act as the target and the source for the ancestor and the cursor binding:


    Code
    public sealed class Intermediary : Control {
        public static readonly DependencyProperty Sync1Property = DependencyProperty.Register( "Sync1", typeof( object ), typeof( Intermediary ), new PropertyMetadata( OnSyncPropertyChanged ) );
        public static readonly DependencyProperty Sync2Property = DependencyProperty.Register( "Sync2", typeof( object ), typeof( Intermediary ), new PropertyMetadata( OnSyncPropertyChanged ) );

        public Intermediary( ) { Visibility = Visibility.Collapsed; }

        public object Sync1 {
            get { return (object)GetValue( Sync1Property ); }
            set { SetValue( Sync1Property, value ); }
        }

        public object Sync2 {
            get { return (object)GetValue( Sync2Property ); }
            set { SetValue( Sync2Property, value ); }
        }

        private static void OnSyncPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) {
            DependencyProperty otherSyncProperty = e.Property == Sync2Property ? Sync1Property : Sync2Property;
            d.SetValue( otherSyncProperty, e.NewValue );
        }
    }

    XAML
    <ni:Graph ...>
        <ni:Graph.Children>
            <ni:MultiPlotCursor x:Name="cursor" ... />
        </ni:Graph.Children>
    </ni:Graph>

    <local:Intermediary x:Name="intermediary"
                        Sync1="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.MarkerXValue, Mode=TwoWay}"
                        Sync2="{Binding ElementName=cursor, Path=AxisValue, Mode=TwoWay}" />


Here, the binding from the cursor to the

~ Paul H
0 Kudos
Message 5 of 7
(6,820 Views)

Thanks that works great

0 Kudos
Message 6 of 7
(6,798 Views)

Just wanted to let you know this issue (#437538) was fixed in the Measurement Studio 2015 release.

~ Paul H
0 Kudos
Message 7 of 7
(5,402 Views)