This is a migrated thread and some comments may be shown as answers.

Cannot nind Visibility property of a Gauge Range

4 Answers 148 Views
Gauges
This is a migrated thread and some comments may be shown as answers.
Ludovic Gerbault
Top achievements
Rank 1
Ludovic Gerbault asked on 13 Oct 2014, 09:46 AM
Hello,

So here's my problem.
I'm building an extended control based of a SemiCircleGauge. That gauge includes 3 ranges that are always visible, but with min and max value set at runtime.
There is also a fourth range that may or may not be visible, property also set at runtime.
I can bind every other value the way I want to, but not the visibility property. For some reason, it always shows regardless of the value I sent it.

Here's all related code :

XAML of the custom control

<telerik:SemicircleNorthScale x:Name="RudderGaugeScale"
    SweepAngle="140"
    StartAngle="200"
    ShowFirstLabel="False"
    ShowLastLabel="False"
    LabelRotationMode="None"
    MiddleTicks="1"
    MajorTickStep="5"
    EndWidth="0.2"
    StartWidth="0.2"
    FontSize="9.333"
    FontWeight="Bold"
    Foreground="White"
    LabelLocation="OverOutside"
    MajorTickLocation="CenterInside"
    MiddleTickStroke="#00000000"
    MinorTickBackground="#00000000"
    MajorTickStroke="White"
    MiddleTickBackground="#00000000"
    MajorTickBackground="White"
    MajorTickUseRangeColor="True"
    MinorTickStroke="#01FFFFFF"
    MajorTickStrokeThickness="1" >
    <telerik:SemicircleNorthScale.Resources>
        <helpers:BindingProxy x:Key="proxy" Data="{Binding ElementName=RudderGauge}" />
    </telerik:SemicircleNorthScale.Resources>
    <telerik:SemicircleNorthScale.Min>           
        <MultiBinding Converter="{StaticResource AngleScaleDisplayConverter}">
            <Binding ElementName="RudderGauge" Path="MinValue" />
            <Binding ElementName="RudderGauge" Path="DeadAngle" />
        </MultiBinding>
    </telerik:SemicircleNorthScale.Min>
    <telerik:SemicircleNorthScale.Max>
        <MultiBinding Converter="{StaticResource AngleScaleDisplayConverter}">
            <Binding ElementName="RudderGauge" Path="MaxValue" />
            <Binding ElementName="RudderGauge" Path="DeadAngle" />
        </MultiBinding>
    </telerik:SemicircleNorthScale.Max>
    <telerik:SemicircleNorthScale.Ranges>
        <telerik:GaugeRange x:Name="DangerZone1" Background="{Binding Path=ColorDanger, ElementName=RudderGauge, Converter={StaticResource ColorConverter}}" Min="{Binding ElementName=RudderGaugeScale, Path=Min}" Max="{Binding ElementName=RudderGauge, Path=DangerMin}" StartWidth="0.8" />
        <telerik:GaugeRange x:Name="DefaultRange" Min="{Binding ElementName=RudderGauge, Path=DangerMin}" Max="{Binding ElementName=RudderGauge, Path=DangerMax}" Background="{Binding ColorDisplay, ElementName=RudderGauge, Converter={StaticResource ColorConverter}}"  StartWidth="0.8" />
        <telerik:GaugeRange x:Name="Sector2" Min="{Binding ElementName=RudderGauge, Path=Sector2Value}" Max="{Binding ElementName=RudderGauge, Path=DangerMax}" Background="{Binding ColorSector2, ElementName=RudderGauge, Converter={StaticResource ColorConverter}}" Visibility="{Binding Path=Data.DisplaySector2, ElementName=RudderGauge, Converter={StaticResource VisibilityConverter} diagnostics:PresentationTraceSources.TraceLevel=High}" StartWidth="0.8" />
        <telerik:GaugeRange x:Name="DangerZone2" Min="{Binding ElementName=RudderGauge, Path=DangerMax}" Max="{Binding ElementName=RudderGaugeScale, Path=Max}" Background="{Binding ColorDanger, ElementName=RudderGauge, Converter={StaticResource ColorConverter}}" StartWidth="0.8" />
    </telerik:SemicircleNorthScale.Ranges>
    <telerik:SemicircleNorthScale.Indicators>
        <telerik:Needle Value="{Binding ElementName=RudderGauge, Path=CurrentValue}"  />
        <telerik:Marker Value="{Binding ElementName=RudderGauge, Path=SetPoint}" Visibility="{Binding ElementName=RudderGauge, Path=DisplaySetPoint, Converter={StaticResource VisibilityConverter}}"  />
    </telerik:SemicircleNorthScale.Indicators>
</telerik:SemicircleNorthScale>

Code behind of the dependency property
public static DependencyProperty DisplaySector2Property = DependencyProperty.Register("DisplaySector2",
    typeof(bool),
    typeof(ECARudderGauge),
    new PropertyMetadata(DisplaySector2PropertyChanged));
 
public bool DisplaySector2
{
    get { return (bool)GetValue(DisplaySector2Property); }
    set { SetValue(DisplaySector2Property, value); }
}
 
private static void DisplaySector2PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    ((ECARudderGauge)o).OnDisplaySector2PropertyChanged((bool)e.NewValue);
}
 
private void OnDisplaySector2PropertyChanged(bool newValue)
{
    DisplaySector2 = newValue;
}

Converter

using System;
using System.Windows;
using System.Windows.Data;
using System.Globalization;
 
namespace ECAControls.Converters
{
    public class VisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool param = (bool)value;
            if (param)
                return Visibility.Visible;
            else
                return Visibility.Collapsed;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Visibility state = (Visibility)value;
            if (state == Visibility.Visible)
                return true;
            else
                return false;
        }
    }
}

Call of the custom control

<eca:ECARudderGauge x:Name="test1" Grid.Row="0" Grid.Column="1"
                           MinValue="{Binding Path=Rudder.MinValue}"
                           MaxValue="{Binding Path=Rudder.MaxValue}"
                           Steps="{Binding Path=Rudder.Steps, Mode=TwoWay}"
                           CurrentValue="{Binding Path=Rudder.CurrentValue, Mode=TwoWay}"
                           SetPoint="{Binding Path=Rudder.SetPoint, Mode=TwoWay}"
                           DisplaySetPoint="{Binding Path=Rudder.DisplaySetPoint, Mode=TwoWay}"
                           ValidateMeasure="{Binding Path=Rudder.ValidateMeasure, Mode=TwoWay}"
                           StopValue="{Binding Path=Rudder.StopValue, Mode=TwoWay}"
                           Sector2Value="{Binding Path=Rudder.Sector2Value, Mode=TwoWay}"
                           DangerMin="{Binding Path=Rudder.DangerMin, Mode=TwoWay}"
                           DangerMax="{Binding Path=Rudder.DangerMax, Mode=TwoWay}"
                           DeadAngle="{Binding Path=Rudder.DeadAngle, Mode=TwoWay}"
                           DisplaySector2="{Binding Path=Rudder.DisplaySector2, Mode=TwoWay}"
                           Text1="{Binding Path=Rudder.Text1, Mode=TwoWay}"
                           Text2="{Binding Path=Rudder.Text2, Mode=TwoWay}"
                           ColorDisplay="{Binding Path=Rudder.ColorDisplay, Mode=TwoWay}"
                           ColorValue="{Binding Path=Rudder.ColorValue, Mode=TwoWay}"
                           ColorScale="{Binding Path=Rudder.ColorScale, Mode=TwoWay}"
                           ColorSetPoint="{Binding Path=Rudder.ColorSetPoint, Mode=TwoWay}"
                           ColorStop="{Binding Path=Rudder.ColorStop, Mode=TwoWay}"
                           ColorSector2="{Binding Path=Rudder.ColorSector2, Mode=TwoWay}"
                           ColorDanger="{Binding Path=Rudder.ColorDanger, Mode=TwoWay}"
                           ColorNeedle1="{Binding Path=Rudder.ColorNeedle1, Mode=TwoWay}"
                           ColorNeedle2="{Binding Path=Rudder.ColorNeedle2, Mode=TwoWay}"
                           ForeColorCurrentVal="{Binding Path=Rudder.ForeColorCurrentVal, Mode=TwoWay}"
                           BackColorCurrentVal="{Binding Path=Rudder.BackColorCurrentVal, Mode=TwoWay}"/>

Diag trace of the binding

01.System.Windows.Data Warning: 56 : Created BindingExpression (hash=32089967) for Binding (hash=25935173)
02.System.Windows.Data Warning: 58 :   Path: 'DisplaySector2'
03.System.Windows.Data Warning: 60 : BindingExpression (hash=32089967): Default mode resolved to OneWay
04.System.Windows.Data Warning: 61 : BindingExpression (hash=32089967): Default update trigger resolved to PropertyChanged
05.System.Windows.Data Warning: 62 : BindingExpression (hash=32089967): Attach to Telerik.Windows.Controls.Gauge.GaugeRange.Visibility (hash=11099805)
06.System.Windows.Data Warning: 64 : BindingExpression (hash=32089967): Use Framework mentor <null>
07.System.Windows.Data Warning: 67 : BindingExpression (hash=32089967): Resolving source
08.System.Windows.Data Warning: 69 : BindingExpression (hash=32089967): Framework mentor not found
09.System.Windows.Data Warning: 65 : BindingExpression (hash=32089967): Resolve source deferred
10.System.Windows.Data Warning: 95 : BindingExpression (hash=32089967): Got InheritanceContextChanged event from GaugeRange (hash=11099805)
11.System.Windows.Data Warning: 67 : BindingExpression (hash=32089967): Resolving source
12.System.Windows.Data Warning: 70 : BindingExpression (hash=32089967): Found data context element: <null> (OK)
13.System.Windows.Data Warning: 74 :     Lookup name RudderGauge:  queried SemicircleNorthScale (hash=21772565)
14.System.Windows.Data Warning: 78 : BindingExpression (hash=32089967): Activate with root item ECARudderGauge (hash=61735358)
15.System.Windows.Data Warning: 108 : BindingExpression (hash=32089967):   At level 0 - for ECARudderGauge.DisplaySector2 found accessor DependencyProperty(DisplaySector2)
16.System.Windows.Data Warning: 104 : BindingExpression (hash=32089967): Replace item at level 0 with ECARudderGauge (hash=61735358), using accessor DependencyProperty(DisplaySector2)
17.System.Windows.Data Warning: 101 : BindingExpression (hash=32089967): GetValue at level 0 from ECARudderGauge (hash=61735358) using DependencyProperty(DisplaySector2): 'False'
18.System.Windows.Data Warning: 80 : BindingExpression (hash=32089967): TransferValue - got raw value 'False'
19.System.Windows.Data Warning: 82 : BindingExpression (hash=32089967): TransferValue - user's converter produced 'Collapsed'
20.System.Windows.Data Warning: 89 : BindingExpression (hash=32089967): TransferValue - using final value 'Collapsed'
21.System.Windows.Data Warning: 79 : BindingExpression (hash=32089967): Deactivate
22.System.Windows.Data Warning: 103 : BindingExpression (hash=32089967): Replace item at level 0 with {NullDataItem}
23.System.Windows.Data Warning: 63 : BindingExpression (hash=32089967): Detach

Please feel free to point out my mistake, I must be missing something somewhere. And I'd really like to avoid setting the visibility in code behind
Thank you

4 Answers, 1 is accepted

Sort by
0
Ludovic Gerbault
Top achievements
Rank 1
answered on 13 Oct 2014, 01:56 PM
Seems my problem might not be my code after all.
Setting the visibility property to either collapsed or hidden still doesn't hide the range.
0
Martin Ivanov
Telerik team
answered on 16 Oct 2014, 08:36 AM
Hello Subileau,

Indeed, this behavior is not caused by your implementation. It appears because the gauge control is handling the range's Visibility property in its code. Setting a property (or binding) in code has a higher priority than binding in xaml.

In order to hide the ranges you can use several approaches. For example you can bind the Background property instead of the Visibility and change it between the range's original color and a Transparent brush based on the DisplaySector2 bool property.

Another approach could be to define an attached property and in its OnPropertyChangedCallback handler to change the range's Visibility.

public class GaugeUtilities
{
    public static bool GetIsRangeVisible(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsRangeVisibleProperty);
    }
 
    public static void SetIsRangeVisible(DependencyObject obj, bool value)
    {
        obj.SetValue(IsRangeVisibleProperty, value);
    }
 
    public static readonly DependencyProperty IsRangeVisibleProperty =
        DependencyProperty.RegisterAttached("IsRangeVisible", typeof(bool), typeof(GaugeUtilities), new PropertyMetadata(true, OnRangeVisibilityChanged));
 
    private static void OnRangeVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {  
        var range = d as GaugeRange;
        var isVisible = (bool)e.NewValue;
        range.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed;
    }
}
.
<telerik:GaugeRange x:Name="Sector2" Min="{Binding ElementName=RudderGauge, Path=Sector2Value}" Max="{Binding ElementName=RudderGauge, Path=DangerMax}" Background="{Binding ColorSector2, ElementName=RudderGauge, Converter={StaticResource ColorConverter}}" StartWidth="0.8" local:GaugeUtilities.IsRangeVisible="{Binding ElementName=RudderGauge, Path=Data.DisplaySector2, IsAsync=True}" />
Note that, the IsAsync property of the binding is set to true. This is because the attached property callback kicks in before the internal setting of the Visibility.

For your convenience I prepared a project demonstrating those approaches. Please give it a try and let me know if they are suitable for your case.

Regards,
Martin
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Ludovic Gerbault
Top achievements
Rank 1
answered on 16 Oct 2014, 02:22 PM
I actually had solved it using a multivalueconverter on my background binding and a secondary binding on the stroke property (visual specificity of my application)

I still think of it as a weird and unexpected behavior, if not an actual bug, to not be able to set the visibility property of a range.
FYI, I had build a test project with basically one semicirclenorthgauge, one scale from 0 to 100, and one range from 0 to 10 with visibility set at collapsed. It still showed up regardless.
0
Martin Ivanov
Telerik team
answered on 20 Oct 2014, 12:08 PM
Hi Subileau,

I am glad to hear that you achieved your requirement.

As for the Visibility issues I can confirm setting the Visibility of GaugeRange in xaml does not work. I logged this issue in our feedback portal where you can track its status and vote. If you follow the feedback item you will be notified by email as soon as its status changes. I also updated your Telerik points as a small gesture of gratitude for reporting the issue.

As a side note, if you set the Visibility in code after the range is loaded, the property's value is applied correctly.

Regards,
Martin
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
Tags
Gauges
Asked by
Ludovic Gerbault
Top achievements
Rank 1
Answers by
Ludovic Gerbault
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or