WPF开发Arcgis的时候如果在地图上添加点图标是很容易实现的,自定义一下Symbol的模板即可实现。但是如果模板中标题文字不固定的时候,点图标没法做偏移(点图标在地图上锚定的时候是以左上角的点位锚定点,如果图标的下部中点和锚点重合就没有这个问题),这样会造成放大和缩小地图的时候点图标乱动的效果。线面介绍一种做偏移的方法,基本思路是使用3个俯角属性绑定模板中控件的实际宽高及模板数据源Symbol,然后处理偏移,OffsetX取实际宽的一半,OffsetY取实际高度,代码如下:
    
    首先自定义一个点图标(使用现有的PictureMarkerSymbol也行,但是需要附加属性控制字体颜色背景之类的)
    
    ///
    
    /// 模块编号:控件库
    
    /// 作用:带有图片及标题的地图点标识
    
    /// 作者:丁纪名
    
    /// 编写日期:2018-01-22
    
    ///
    
    public class TitlePictureMarkerSymbol : MarkerSymbol
    
    {
    
    ///
    
    /// 图片数据源
    
    ///
    
    public ImageSource Source
    
    {
    
    get { return (ImageSource)GetValue(SourceProperty); }
    
    set { SetValue(SourceProperty, value); }
    
    }
   
    // Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register("Source", typeof(ImageSource), typeof(TitlePictureMarkerSymbol), new PropertyMetadata(null));
    /// <summary>
    /// 标题
    /// </summary>
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(TitlePictureMarkerSymbol), new PropertyMetadata(null));
    /// <summary>
    /// 标题字体大小
    /// </summary>
    public double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }
    // Using a DependencyProperty as the backing store for FontSize.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
                    typeof(TitlePictureMarkerSymbol),
                    new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,
                        FrameworkPropertyMetadataOptions.Inherits));
    /// <summary>
    /// 标题前景色
    /// </summary>
    public Brush Foreground
    {
        get { return (Brush)GetValue(ForegroundProperty); }
        set { SetValue(ForegroundProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Foreground.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ForegroundProperty = TextElement.ForegroundProperty.AddOwner(
                    typeof(TitlePictureMarkerSymbol),
                    new FrameworkPropertyMetadata(SystemColors.ControlTextBrush,
                        FrameworkPropertyMetadataOptions.Inherits));
    /// <summary>
    /// 文本背景色
    /// </summary>
    public Brush Background
    {
        get { return (Brush)GetValue(BackgroundProperty); }
        set { SetValue(BackgroundProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BackgroundProperty = Panel.BackgroundProperty.AddOwner(typeof(TitlePictureMarkerSymbol),
                new FrameworkPropertyMetadata(
                    Panel.BackgroundProperty.DefaultMetadata.DefaultValue,
                    FrameworkPropertyMetadataOptions.None));
    public static double GetWidth(DependencyObject obj)
    {
        return (double)obj.GetValue(WidthProperty);
    }
    public static void SetWidth(DependencyObject obj, double value)
    {
        obj.SetValue(WidthProperty, value);
    }
    // Using a DependencyProperty as the backing store for Width1.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty WidthProperty =
        DependencyProperty.RegisterAttached("Width", typeof(double), typeof(TitlePictureMarkerSymbol), new FrameworkPropertyMetadata(default(double), new PropertyChangedCallback(OnWidthChanged)));
    private static void OnWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = d as FrameworkElement;
        if (element != null)
        {
            TitlePictureMarkerSymbol symbol = TitlePictureMarkerSymbol.GetSymbol(element) as TitlePictureMarkerSymbol;
            if (symbol != null)
            {
                symbol.OffsetX = element.ActualWidth / 2;
            }
        }
    }
    public static double GetHeight(DependencyObject obj)
    {
        return (double)obj.GetValue(HeightProperty);
    }
    public static void SetHeight(DependencyObject obj, double value)
    {
        obj.SetValue(HeightProperty, value);
    }
    // Using a DependencyProperty as the backing store for Height1.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeightProperty =
        DependencyProperty.RegisterAttached("Height", typeof(double), typeof(TitlePictureMarkerSymbol), new FrameworkPropertyMetadata(default(double), new PropertyChangedCallback(OnHeightChanged)));
    private static void OnHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = d as FrameworkElement;
        if (element != null)
        {
            TitlePictureMarkerSymbol symbol = TitlePictureMarkerSymbol.GetSymbol(element) as TitlePictureMarkerSymbol;
            if (symbol != null)
            {
                symbol.OffsetY = element.ActualHeight;
            }
        }
    }
    public static object GetSymbol(DependencyObject obj)
    {
        return (object)obj.GetValue(SymbolProperty);
    }
    public static void SetSymbol(DependencyObject obj, object value)
    {
        obj.SetValue(SymbolProperty, value);
    }
    // Using a DependencyProperty as the backing store for Symbol.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SymbolProperty =
        DependencyProperty.RegisterAttached("Symbol", typeof(object), typeof(TitlePictureMarkerSymbol), new PropertyMetadata(null));
}
    定义模板:
    
    
    
    使用方式:
    
    var symbol = new TitlePictureMarkerSymbol
    
    {
    
    Source = img,
    
    Background = Brushes.DimGray,
    
    FontSize = 12,
    
    Foreground = Brushes.White
    
    };
    
    symbol.ControlTemplate = SymbolResource.Resource[“TitlePictureMarkerSymbolStyle”] as ControlTemplate;
    
    如此即可实现不固定宽度的图片文本点图标了。
   
 
