Ranges databinding in Custom Control

4 posts, 0 answers
  1. Wenrong
    Wenrong avatar
    36 posts
    Member since:
    May 2012

    Posted 11 Jul 2014 Link to this post

    Data binding doesn't work when the Gauge control is hosted inside a Custom Control (we need to use Custom control for better performance)

    See sample code below, the Gauge in MainWindow binds fine with the Ranges, but not the Gauge inside the custom control.

    MainWindow.xaml
    <Window x:Class="GaugeTest.MainWindow"
            xmlns:local="clr-namespace:GaugeTest"
            Title="MainWindow" Height="638" Width="575">
        <StackPanel>
            <telerik:RadRadialGauge Name="PART_Gauge" Width="220" Height="220">
                <telerik:RadialScale Name="scale"
                                     RangeLocation="Outside"
                                     LabelRotationMode="None"
                                     Radius="0.93"
                                     Ranges="{Binding Ranges}">
     
                    <telerik:RadialScale.Indicators>
                        <telerik:BarIndicator Name="radialBar"
                                              UseRangeColor="True"
                                              RangeColorMode="ProportionalBrush"
                                              StartWidth="0.06"
                                              telerik:ScaleObject.Location="Outside"
                                              telerik:ScaleObject.Offset="0.01*"
                                              Value="0" />
                    </telerik:RadialScale.Indicators>
                </telerik:RadialScale>
            </telerik:RadRadialGauge>
            <local:RadialGaugeControl Width="220" Height="220" />
        </StackPanel>
    </Window>

    MainWindow.cs
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Media;
    using Telerik.Windows.Controls;
    using Telerik.Windows.Controls.Gauge;
     
    namespace GaugeTest
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                scale.SetCurrentValue(ScaleBase.RangesProperty, new GaugeRangeCollection());
     
                this.DataContext = new MainWindowViewModel();
            }
        }
     
        public class MainWindowViewModel : ViewModelBase
        {
            public MainWindowViewModel()
            {
                Ranges = new GaugeRangeCollection();
                AddRange(0, 30, Colors.Green);
                AddRange(30, 60, Colors.Yellow);
                AddRange(60, 100, Colors.Orange);
            }
     
            private void AddRange(double min, double max, Color color)
            {
                GaugeRange gr = new GaugeRange()
                {
                    Min = min,
                    Max = max,
                    StartWidth = 0.01,
                    EndWidth = 0.01,
                    Background = new SolidColorBrush(color),
                    IndicatorBackground = new SolidColorBrush(color),
                    TickBackground = new SolidColorBrush(color),
                    LabelForeground = new SolidColorBrush(color),
                };
                gr.PropertyChanged += (s, e) =>
                {
                    if (e.PropertyName == "Background")
                    {
                        // make sure they are in sync
                        gr.IndicatorBackground = gr.Background;
                        gr.TickBackground = gr.Background;
                        gr.LabelForeground = gr.Background;
                    }
                };
                Ranges.Add(gr);
            }
     
            private GaugeRangeCollection _ranges;
            public GaugeRangeCollection Ranges
            {
                get
                {
                    return _ranges;
                }
                set
                {
                    _ranges = value;
                    OnPropertyChanged(() => Ranges);
                }
            }
        }
    }

    RadialGaugeControl.cs
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
     
    namespace GaugeTest
    {
        public class RadialGaugeControl : Control
        {
            static RadialGaugeControl()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(RadialGaugeControl), new FrameworkPropertyMetadata(typeof(RadialGaugeControl)));
            }
        }
    }

    Theme\Generic.xaml
    <ResourceDictionary
        xmlns:local="clr-namespace:GaugeTest">
     
     
        <Style TargetType="{x:Type local:RadialGaugeControl}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:RadialGaugeControl}">
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <telerik:RadRadialGauge Name="PART_Gauge" Width="220" Height="220">
                                <telerik:RadialScale Name="PART_Scale"
                                         RangeLocation="Outside"
                                         LabelRotationMode="None"
                                         Radius="0.93"
                                                 Ranges="{Binding Ranges}">
     
                                    <telerik:RadialScale.Indicators>
                                        <telerik:BarIndicator Name="radialBar"
                                                  UseRangeColor="True"
                                                  RangeColorMode="ProportionalBrush"
                                                  StartWidth="0.06"
                                                  telerik:ScaleObject.Location="Outside"
                                                  telerik:ScaleObject.Offset="0.01*"
                                                  Value="0" />
                                    </telerik:RadialScale.Indicators>
                                </telerik:RadialScale>
                            </telerik:RadRadialGauge>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>

    App.xaml
    <Application x:Class="GaugeTest.App"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="/Telerik.Windows.Themes.Windows8;component/Themes/Telerik.Windows.Controls.xaml" />
                    <ResourceDictionary Source="/Telerik.Windows.Themes.Windows8;component/Themes/Telerik.Windows.Controls.DataVisualization.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>

  2. Paul
    Paul avatar
    38 posts
    Member since:
    Feb 2014

    Posted 17 Sep 2014 in reply to Wenrong Link to this post

    Has there been a solution to this?

    I am encountering a similar issue with using a Ranges binding in a Data Template.  the ranges don't show. 
    <DataTemplate DataType="{x:Type local:Measure}">
                    <telerik:RadRadialGauge MinWidth="200"
                                            MinHeight="200">
                        <telerik:RadialScale Ranges="{Binding  Path=Ranges}">
                            <telerik:RadialScale.Indicators>
                                <telerik:BarIndicator UseRangeColor="True"
                                                      RangeColorMode="Default"
                                                      EmptyFill="Transparent"
                                                      Background="Transparent"
                                                      StartWidth=".07"
                                                      EndWidth=".07"
                                                      telerik:ScaleObject.Location="OverOutside"
                                                      telerik:ScaleObject.Offset="0.01*"
                                                      Value="50"
                                                      HorizontalContentAlignment="Stretch"
                                                      VerticalContentAlignment="Stretch" />
                            </telerik:RadialScale.Indicators>
                        </telerik:RadialScale>
                    </telerik:RadRadialGauge>
                </DataTemplate>
  3. UI for WPF is Visual Studio 2017 Ready
  4. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 18 Sep 2014 Link to this post

    Hi Paul,

    I already answered your question in a support ticket, but I am posting it also here so our community can benefit from it.

    In order to resolve this you can create an attached property that will bind the Ranges collection in code. Here is an example:

    public class GaugeUtilities
    {
        public static IEnumerable GetRanges(DependencyObject obj)
        {
            return (IEnumerable)obj.GetValue(RangesProperty);
        }
     
        public static void SetRanges(DependencyObject obj, IEnumerable value)
        {
            obj.SetValue(RangesProperty, value);
        }
     
        // Using a DependencyProperty as the backing store for Ranges.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RangesProperty =
            DependencyProperty.RegisterAttached("Ranges"typeof(IEnumerable),typeof(GaugeUtilities), new PropertyMetadata(null, OnRangesPropertyChanged));
     
        private static void OnRangesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RadialScale scale = (RadialScale)d;
            var ranges = e.NewValue as GaugeRangeCollection;
            if (ranges != null)
            {
                var binding = new Binding() { Source = ranges };
                scale.SetBinding(ScaleBase.RangesProperty, binding);
            }
        }
    }

    <telerik:RadialScale local:GaugeUtilities.Ranges="{Binding ElementName=rbi,  Path=DataContext.Ranges, Converter={StaticResource conv}}">

    Regards,
    Martin
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  5. Paul
    Paul avatar
    38 posts
    Member since:
    Feb 2014

    Posted 18 Sep 2014 in reply to Martin Link to this post

    Thank you, the fix worked for my case.

    Paul Montgomery
Back to Top