Select to view content in your preferred language

Access ScaleBars Current Value?

2671
7
10-15-2010 12:58 PM
RyanCoodey
Frequent Contributor
Is there a way to access the ScaleBars distance value?  I could not find any properties or events that would give me access to it.

What I am tring to do is change the DisplayUnit programatically.  If the value is < 1 mile, then change the DisplayUnit to feet, and if it is > 5279 ft switch to miles.

Thanks for any help!
0 Kudos
7 Replies
JenniferNery
Esri Regular Contributor
The ScaleBar value gets updated when map extent changes so you can subscribe to your map's ExtentChanged event.
0 Kudos
RyanCoodey
Frequent Contributor
Thanks Jennifer!  But how do I access the ScaleBars current value (i.e. 3 Miles, 1 Mile, etc)?
0 Kudos
JenniferNery
Esri Regular Contributor
If you have Expression Blend, you can get the template of ScaleBar, notice that one of its Template parts is ScaleBarValue. You can subscribe to its Loaded event and access its Text value on Map_ExtentChanged (see snippets below).

XAML:
<Style x:Key="ScaleBarStyle" TargetType="esri:ScaleBar">
   <Setter Property="FillColor1" Value="White"/>
   <Setter Property="FillColor2" Value="Black"/>
   <Setter Property="TextColor" Value="White"/>
   <Setter Property="TargetWidth" Value="150.0"/>
   <Setter Property="FontSize" Value="10.0"/>
   <Setter Property="BarHeight" Value="10.0"/>
   <Setter Property="Foreground" Value="White"/>
   <Setter Property="Template">
    <Setter.Value>
     <ControlTemplate TargetType="esri:ScaleBar">
      <StackPanel Orientation="Horizontal">
       <Grid x:Name="ScaleBarBlock" Height="{TemplateBinding BarHeight}" VerticalAlignment="Center">
        <Grid.ColumnDefinitions>
         <ColumnDefinition Width="1*"/>
         <ColumnDefinition Width="1*"/>
         <ColumnDefinition Width="1*"/>
         <ColumnDefinition Width="2*"/>
         <ColumnDefinition Width="5*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
         <RowDefinition Height="1*"/>
         <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Rectangle Grid.Column="0" Fill="{TemplateBinding FillColor2}" Grid.Row="0"/>
        <Rectangle Grid.Column="1" Fill="{TemplateBinding FillColor1}" Grid.Row="0"/>
        <Rectangle Grid.Column="2" Fill="{TemplateBinding FillColor2}" Grid.Row="0"/>
        <Rectangle Grid.Column="3" Fill="{TemplateBinding FillColor1}" Grid.Row="0"/>
        <Rectangle Grid.Column="4" Fill="{TemplateBinding FillColor2}" Grid.Row="0"/>
        <Rectangle Grid.Column="0" Fill="{TemplateBinding FillColor1}" Grid.Row="1"/>
        <Rectangle Grid.Column="1" Fill="{TemplateBinding FillColor2}" Grid.Row="1"/>
        <Rectangle Grid.Column="2" Fill="{TemplateBinding FillColor1}" Grid.Row="1"/>
        <Rectangle Grid.Column="3" Fill="{TemplateBinding FillColor2}" Grid.Row="1"/>
        <Rectangle Grid.Column="4" Fill="{TemplateBinding FillColor1}" Grid.Row="1"/>
       </Grid>
       <TextBlock x:Name="ScaleBarValue" Loaded="ScaleBarValue_Loaded" Foreground="{TemplateBinding TextColor}" VerticalAlignment="Center"/>
      </StackPanel>
     </ControlTemplate>
    </Setter.Value>
   </Setter>
  </Style>


Code-behind:
       TextBlock scaleBarValue;
        private void ScaleBarValue_Loaded(object sender, RoutedEventArgs e)
        {
            scaleBarValue = sender as TextBlock;
            
        }

        private void MyMap_ExtentChanged(object sender, ESRI.ArcGIS.Client.ExtentEventArgs e)
        {
            //check for scaleBarValue.Text
        }
0 Kudos
RyanCoodey
Frequent Contributor
Great, thanks for that info Jennifer!

Here is what I did...

        private void ScaleBar_Loaded(object sender, RoutedEventArgs e)
        {
            ScaleBar.ApplyTemplate();
            ScaleBarValueTextBlock = ScaleBar.Template.FindName("ScaleBarValue", ScaleBar) as TextBlock;
        }

        private void Map_ExtentChanged(object sender, ESRI.ArcGIS.Client.ExtentEventArgs e)
        {
            if (ScaleBarValueTextBlock != null)
            {
                if (ScaleBar.DisplayUnit == ScaleBarUnit.Miles && ScaleBarValueTextBlock.Text[0] == '0')
                    ScaleBar.DisplayUnit = ScaleBarUnit.Feet;
                else if (ScaleBar.DisplayUnit == ScaleBarUnit.Feet && Convert.ToDouble(ScaleBarValueTextBlock.Text.TrimEnd(" Feet".ToCharArray())) > 5279)
                    ScaleBar.DisplayUnit = ScaleBarUnit.Miles;
            }
        }



If anyone has any String to Int performance tips to replace "Convert.ToDouble(ScaleBarValueTextBlock.Text.TrimEnd(" Feet".ToCharArray()))" with, that would be great?  I hate having to do that much string manipulation in an event like that.

Also, if the API developers don't have an issue with it, maybe in a future version could make the actual double value property public and read-only to the users?

Thanks a lot!
0 Kudos
JenniferNery
Esri Regular Contributor

Also, if the API developers don't have an issue with it, maybe in a future version could make the actual double value property public and read-only to the users?

I'll forward your request to our team lead for discussion.

You can do this for conversion to double:
                string stringValue = ScaleBarValueTextBlock.Text.Replace(ScaleBar.DisplayUnit.ToString(), string.Empty).Trim();
                double doubleValue = Convert.ToDouble(stringValue, CultureInfo.InvariantCulture);
                // or this below
                //double doubleValue = double.IsNaN;
                //double.TryParse(stringValue, out doubleValue);
0 Kudos
DanDong
Deactivated User
Hi,

in these codes:

private void ScaleBar_Loaded(object sender, RoutedEventArgs e)
        {
            ScaleBar.ApplyTemplate();
            ScaleBarValueTextBlock = ScaleBar.Template.FindName("ScaleBarValue", ScaleBar) as TextBlock;
        }

i give the scalebar a name as MyScaleBar. so mine is like this.

private void ScaleBar_Loaded(object sender, RoutedEventArgs e)
        {
            MyScaleBar.ApplyTemplate();
            ScaleBarValueTextBlock = MyScaleBar.Template.FindName("ScaleBarValue", MyScaleBar) as TextBlock;
        }

But there seems some error: with the codes.
Error 3 'System.Windows.Controls.ControlTemplate' does not contain a definition for 'FindName' and no extension method 'FindName' accepting a first argument of type 'System.Windows.Controls.ControlTemplate' could be found (are you missing a using directive or an assembly reference?) D:\AGS_mxd\dan\Final_backup\Final\MainPage.xaml.cs 398 58 Final

so i change the codes to
ScaleBarValueTextBlock = MyScaleBar.FindName("ScaleBarValue") as TextBlock;
then i put
messagebox.show ("value"+ScaleBarValueTextBlock.Text);
to see whether ScaleBarValueTextBlock.Text has something on it.
When i run the prj, there is a messagebox showing. There is only "value" on the messagebox, i mean these five letters, seems it didn't give the text on it.

Did I make some mistakes on it. Thank you for the advice.
0 Kudos
JenniferNery
Esri Regular Contributor
Hi. I'm sorry I think Ryan is using WPF. If you are using Silverlight, I think using Loaded event is fine.  But still try to do one step at a time as I suggested in the other thread.  Make sure that the map and scalebar loads fine with this style before changing anything else so we know atleast that part works.
0 Kudos