Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

gaugedouble range binding

Solved!
Go to solution

Hello,

i've a Problem by Setting the Range of an GaugeDouble with MVVM

 

Here is my Code that doesn't work. Hope anyboy can help me:

 

 <ni:GaugeDouble  Range="{Binding GaugeRange}"  Value="{Binding Value}" Width="auto" />

and in my Viewmodel

 private Range<double> _GaugeRange;
         public Range<double> GaugeRange
         {
             get { return _GaugeRange; }
             set
             {
                 _GaugeRange = value;

                 NotifyPropertyChanged("GaugeRange");
             }
         }

 Thanks for your help

0 Kudos
Message 1 of 9
(7,439 Views)

There is a known issue with how the numeric scale synchronizes its range with the numeric control when it is initialized. Instead of assigning Range only after it has been edited interactively, it will assign it when the scale is initialized, overriding the binding.


Instead, you will need to use a two-way binding:


    <ni:GaugeDouble Range="{Binding GaugeRange, Mode=TwoWay}" ... />

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

Hi Paul,

thanks for your Answer.

I tried the Two-Way Binding but it doesnt work!

I have

 

GaugeRange = new Range<double>(-900,900);

Is that ok ?

 

What else can i try ?

0 Kudos
Message 3 of 9
(7,424 Views)

Here is the complete example I used to test the two-way binding:


    Code
    using NationalInstruments.Controls;
    using System;
    using System.ComponentModel;
    using System.Windows;

    namespace GaugeRangeBinding {

        public class Model : INotifyPropertyChanged {
            private Range<double> _GaugeRange = new Range<double>( -1.0, 1.0 );
            public Range<double> GaugeRange {
                get { return _GaugeRange; }
                set {
                    _GaugeRange = value;
                    NotifyPropertyChanged( "GaugeRange" );
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged( string propertyName ) {
                var handler = this.PropertyChanged;
                if( handler != null )
                    handler( this, new PropertyChangedEventArgs( propertyName ) );
            }
        }

        public partial class MainWindow : Window {
            public MainWindow( ) {
                InitializeComponent( );
            }

            private void OnMouseUp( object sender, EventArgs e ) {
                var model = (Model)textBox.DataContext;
                var range = model.GaugeRange;
                model.GaugeRange = new Range<double>( range.Minimum, 2 * range.Maximum );
                textBox.Text = model.GaugeRange.ToString( );
            }
        }

    }


    XAML
    <Window x:Class="GaugeRangeBinding.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ni="http://schemas.ni.com/controls/2009/xaml/presentation"
            xmlns:local="clr-namespace:GaugeRangeBinding"
            Title="MainWindow" Height="300" Width="400">
        <Grid>
            <Grid.DataContext>
                <local:Model />
            </Grid.DataContext>

            <ni:GaugeDouble Range="{Binding GaugeRange, Mode=TwoWay}" />
            <TextBlock x:Name="textBox" MouseLeftButtonUp="OnMouseUp" />
        </Grid>
    </Window>


The XAML contains a text block that covers the screen, and clicking the text block causes the OnMouseUp handler to change the range on the model, which updated the gauge via the binding.

~ Paul H
0 Kudos
Message 4 of 9
(7,416 Views)

Hello Paul,

thanks for your Answer. Your Example works fine. but in my Case it isn't working.

I've got the GaugeDouble in an DataTemplate

<DataTemplate x:Key="Gauge">
        
                    <Grid ContextMenu="{StaticResource cmenu}">

                        <Grid.RowDefinitions>
                            <RowDefinition Height="30" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Label Grid.Row="0" Content="{Binding Title}" Padding="6,6,0,0" Background="#A0B2FF" BorderBrush="White" BorderThickness="1" FontSize="14"></Label>
                        <Border BorderBrush="white" Background="Gainsboro" Grid.Row="1" BorderThickness="1,0,1,1" Width="200"
                                        Height="200">
                            <ni:GaugeDouble  Range="{Binding GaugeRange, Mode=TwoWay}"  Value="{Binding Value}" Width="auto" />
                        </Border>
                    </Grid>
              
        
    </DataTemplate>

 The DataTemplate is Used in an ItemsControl. That doesn't work. All other Controls where working fine.

What can be the Issue ?

 

0 Kudos
Message 5 of 9
(7,401 Views)

Here is my complete Solution:

XAML:

        <ItemsControl Grid.Column="0" Grid.ColumnSpan="3" AllowDrop="True"   ItemsSource="{Binding Objects}"  Background="Transparent"  
                       x:Name="DesigningCanvas" 
                      >
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style >
                    <Setter Property="Canvas.Left" Value="{Binding X,Mode=TwoWay}"/>
                    <Setter Property="Canvas.Top" Value="{Binding Y,Mode=TwoWay}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>

                        <Grid.RowDefinitions>
                            <RowDefinition Height="30" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Label Grid.Row="0" Content="{Binding Title}" Padding="6,6,0,0" Background="#A0B2FF" BorderBrush="White" BorderThickness="1" FontSize="14"></Label>
                        <Border BorderBrush="white" Background="Gainsboro" Grid.Row="1" BorderThickness="1,0,1,1" Width="200"
                                        Height="200">
                            <my:GaugeDouble  Range="{Binding GaugeRange, Mode=TwoWay}"  Value="{Binding Value}" Width="auto" />
                        </Border>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
                
        </ItemsControl>

        
    </Grid>

 The Model:

 public class Model : INotifyPropertyChanged
    {


        private ObservableCollection<CanvasObject> _Objects;
        public ObservableCollection<CanvasObject> Objects
        {
            get { return _Objects; }
            set
            {
                _Objects = value;
                NotifyPropertyChanged("Objects");
            }
        }

        public Model()
        {
            Objects = new ObservableCollection<CanvasObject>();
            Objects.Add(new CanvasObject
            {
                Height = 200,
                Width = 200,
                X = 100,
                Y = 100
            });
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    } 

 And here my Object:

 public class CanvasObject : INotifyPropertyChanged
    {
        public CanvasObject()
        {
        
           
        }


       
        private string _Name;
        public string Name
        {
            get { return _Name; }
            set
            {
                _Name = value;
                Title = _Name;
                NotifyPropertyChanged("Name");
            }
        }

        private string _Title;
        public string Title
        {
            get { return _Title; }
            set
            {
                _Title = value;
                NotifyPropertyChanged("Title");
            }
        }

      


        private object _Value;
        public object Value
        {
            get { return _Value; }
            set
            {
                _Value = value;
                NotifyPropertyChanged("Value");
            }
        }


       
        private double _Width;
        public double Width
        {
            get { return _Width; }
            set
            {
                _Width = value;
                NotifyPropertyChanged("Width");
            }
        }

        private double _Height;
        public double Height
        {
            get { return _Height; }
            set
            {
                _Height = value;
                NotifyPropertyChanged("Height");
            }
        }
      

        private Range<double> _GaugeRange = new Range<double>(50, 900);
        public Range<double> GaugeRange
        {
            get { return _GaugeRange; }
            set
            {
                _GaugeRange = value;

                NotifyPropertyChanged("GaugeRange");
            }
        }


        private double _X;
        public double X
        {
            get { return _X; }
            set
            {
                _X = value;
                NotifyPropertyChanged("X");
            }
        }

        private double _Y;
        public double Y
        {
            get { return _Y; }
            set
            {
                _Y = value;
                NotifyPropertyChanged("Y");
            }
        }

        #region PropertyChanged Event Implementation

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }

        #endregion
    }

 The Binding of the Range-Property doesn't work in this case. But why ?

 

0 Kudos
Message 6 of 9
(7,400 Views)
Solution
Accepted by topic author manuelhoedl

With your full code, I was able to reproduce the issue. I am not sure why the binding is being cleared on a control inside a data template, as opposed to the behavior outside.


As a workaround, I have found you can use a binding on a custom attached property that assigns the range directly:


    XAML
    ...
    <ni:GaugeDouble my:Extensions.Range="{Binding GaugeRange}" />
    ...


    Code
    public static class Extensions {

        public static readonly DependencyProperty RangeProperty =
            DependencyProperty.RegisterAttached(
                "Range", typeof( Range<double> ), typeof( Extensions ),
                new PropertyMetadata( OnRangeChanged ) );

        public static Range<double> GetRange( DependencyObject d ) {
            return (Range<double>)d.GetValue( RangeProperty );
        }

        public static void SetRange( DependencyObject d, Range<double> value ) {
            d.SetValue( RangeProperty, value );
        }

        private static void OnRangeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) {
            var pointer = (NumericPointer<double, double>)d;
            pointer.Range = (Range<double>)e.NewValue;
        }

    }

~ Paul H
Message 7 of 9
(7,391 Views)

It works perfect Smiley Very Happy

 

Thank you very much 🙂

0 Kudos
Message 8 of 9
(7,386 Views)

Just wanted to let you know the Range binding issue was fixed in the Measurement Studio 2015 release, and no longer needs the TwoWay mode workaround.

~ Paul H
0 Kudos
Message 9 of 9
(5,814 Views)