Select to view content in your preferred language

Dynamically change color of a symbol

4943
4
06-16-2010 12:22 PM
DennisMcDermott
Emerging Contributor
I have a symbol (see below) I've created that has some nice features to it. What I haven't been able to figure out how to do is to change the color without creating one of these for every color I want to use. Question: is there a way to drill down into the symbol to change the color of the ellipse dynamically?

<esriSymbols:SimpleMarkerSymbol x:Name = "RoundSymbol" >
<esriSymbols:SimpleMarkerSymbol.ControlTemplate>
<ControlTemplate>
<Grid RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1" />
</TransformGroup>
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="SymbolGeom" Storyboard.TargetProperty="Width" To="20" Duration="0:0:0.2" >
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="2"></BackEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation BeginTime="00:00:00" Storyboard.TargetName="SymbolGeom" Storyboard.TargetProperty="Height" To="20" Duration="0:0:0.2" >
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="2"></BackEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse Width="10" Height="10" Fill="Red" Style="{StaticResource DemoMarkerStyle}" x:Name="SymbolGeom"/>
<TextBlock TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="CountTextBlock"
Foreground="White" Text="{Binding Path=Attributes, Converter={StaticResource dictConverter}, ConverterParameter=Count}"/>
</Grid>
</ControlTemplate>
</esriSymbols:SimpleMarkerSymbol.ControlTemplate>
</esriSymbols:SimpleMarkerSymbol>
0 Kudos
4 Replies
dotMorten_esri
Esri Notable Contributor
Instead of using SimpleMarkerSymbol, create your own symbol that inherits from MarkerSymbol (when using custom templates, the Simple*Symbol classes are not recommended). On this class create a property of type Brush.
In your template you can then bind to this using Fil="{Binding Symbol.MyBrushProperty}"
You can also bind to an attribute in the graphic. fx. Fill="{Binding Attributes[MyBrushKey]}".
0 Kudos
rohandontireddy
Emerging Contributor
I think u can use something like this

Symbol _activeSymbol = null;
SimpleMarkerSymbol marker = new SimpleMarkerSymbol();
  marker = new SimpleMarkerSymbol()
           {
               Color = brdrpointdrawfillcolor.Background,
               Size = pointdrawsizeslider.Value,
           };
MyDrawObject.DrawMode = DrawMode.Point;
            _activeSymbol = marker;
0 Kudos
AndyWright
Frequent Contributor
Morten,

Would you be able to post some code showing exactly how you would implement this type of scenario?  I have written a tool that allows users to add various graphics (points, lines, polys) as map markup to a graphics layer.  I need to allow the user to change properties (fill, stroke, size, e.t.c.) for those graphics and have them take on the new characteristics instantaneously.  The scenario described in this thread seems to be exactly what I'll need.

I'm struggling with how to set all of this up.  Can you post some example code showing the XAML where you are defining your marker symbol and bindings, and also some C# code behind showing how you would go about using this marker symbol and updating values that are participating in bindings? 

I currently have an object that is inheriting from MarkerSymbol and a style set up in my generic.xaml file, but can't quite bridge the gap between the two.  Thanks a ton for any help you can provide me here.
0 Kudos
AndyWright
Frequent Contributor
Morten,

Nevermind, I was able to figure this out on my own.  The missing link for me was the ability to access styles/ControlTemplates for my marker symbols contained within a resource dictionary from the object class.  For those of you who are interested, here's how it works.

This is a control template for a circle marker symbol that is contained within a resource dictionary:
<ControlTemplate x:Key="CircleMarkerSymbol">
        <Ellipse x:Name="ellipse"
                 Fill="{Binding Symbol.Color}"
                 Width="{Binding Symbol.Size}"
                 Height="{Binding Symbol.Size}"
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="SelectionStates">
                    <VisualState x:Name="Unselected" />
                    <VisualState x:Name="Selected">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ellipse"
        Storyboard.TargetProperty="Fill">
                                <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{Binding Symbol.SelectionColor}" />
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </Ellipse>
    </ControlTemplate>


This is my object class for the marker symbol.  Notice the code in the constructor where I access the CircleMarkerSymbol ControlTemplate within my resource dictionary file.  That was the key for me to piece this stuff together.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ESRI.ArcGIS.Client.Symbols;


namespace ESRIEditingTest.SymbolClasses
{
    public class SRPDrawMarkerSymbol : MarkerSymbol
    {
        public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Brush), typeof(SRPDrawMarkerSymbol), null);
        public static readonly DependencyProperty SelectionColorProperty = DependencyProperty.Register("SelectionColor", typeof(Brush), typeof(SRPDrawMarkerSymbol), null);
        public static readonly DependencyProperty SizeProperty = DependencyProperty.Register("Size", typeof(double), typeof(SRPDrawMarkerSymbol), null);
        // Methods
        public SRPDrawMarkerSymbol()
        {
            this.Color = new SolidColorBrush(Colors.Red);
            this.SelectionColor = new SolidColorBrush(Colors.Cyan);

            ResourceDictionary resDict = new ResourceDictionary();
            resDict.Source = new Uri("/ESRIEditingTest;component/Themes/ResDict.xaml", UriKind.Relative);
            ControlTemplate = resDict["CircleMarkerSymbol"] as ControlTemplate;
        }

        public Brush Color
        {
            get
            {
                return (Brush)GetValue(ColorProperty);
            }
            set
            {
                SetValue(ColorProperty, value);
            }
        }

        public Brush SelectionColor
        {
            get
            {
                return (Brush)GetValue(SelectionColorProperty);
            }
            set
            {
                SetValue(SelectionColorProperty, value);
            }
        }

        public double Size
        {
            get
            {
                return (double)GetValue(SizeProperty);
            }
            set
            {
                SetValue(SizeProperty, value);
            }
        }
    }
}



And finally the easy part - working with this in code behind.  Here is how you instantiate the marker symbol object and set its properties.  Since these properties are set with bindings in the control template, you can change them on the fly and your marker symbol in the map will reflect those changes automatically.  This code sits in the DrawComplete event of a Draw object.

SRPDrawMarkerSymbol dms = new SRPDrawMarkerSymbol();
                dms.Size = 70;
                dms.Color = new SolidColorBrush(Colors.Green);

                MapPoint p = e.Geometry as MapPoint;
                gr = new Graphic
                {
                    Geometry = p,
                    Symbol = dms
                };