DayDreamInGIS 之 ArcGIS Pro二次开发 图层属性中换行符等特殊字符替换

具体参考ArcMap中类似的问题,本帖开发一个ArcGISPro版的工具

1.基础库部分

插件开发,经常需要处理图层与界面的交互。基础库把常用的交互部分做了封装,方便之后的重复使用。

(1)下述类定义了数据存储结构,主要用于保存Combox中的label与值。比如,Name_Index类,用于保存名称-数值索引,Name_Layer类,用于保存图层名-图层

cs 复制代码
using ArcGIS.Desktop.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GISCommonHelper
{
    /// <summary>
    /// 名称与索引,用于数据绑定时界面的显示,适用于字段名与索引,图层名与索引等
    /// </summary>
    public class Name_Index
    {
        public string name { get; set; }
        public int index { get; set; }

        public Name_Index(string name, int index)
        {
            this.name = name;
            this.index = index;
        }
    }

    /// <summary>
    /// 字段名与假名
    /// </summary>
    public class Name_AliasName
    {
        public string name { get; set; }
        public string alias_name { get; set; }
        public Name_AliasName(string name, string alias_name)
        {
            this.name = name;
            if (string.IsNullOrEmpty(this.alias_name))
            {
                this.alias_name = alias_name;
            }
            else
            {
                this.alias_name = name;
            }
        }
    }

    /// <summary>
    /// 图层名与图层
    /// </summary>
    public class Name_Layer
    {
        public string Name { get; set; }
        public Layer layer { get; set; }
        public Guid id { get; set; }

        public Name_Layer(string name, Layer layer)
        {
            this.Name = name;
            this.layer = layer;
            this.id = Guid.NewGuid();
        }
    }

    public class name_obj
    {
        public string name { get; set; }
        public object obj { get; set; }
        public Guid id { get; set; }
        public string tp { get; set; }

        public name_obj() { }

        public name_obj(string name, object obj, string tp)
        {
            this.name = name;
            this.obj = obj;
            this.tp = tp;
            this.id = Guid.NewGuid();
        }
    }
}

(2)下述代码实通过静态扩展的方式,扩展WPF 中Combox组件,新增方法

setLyrlist<T>,通过数据绑定的形式设置Combox的Items集合,通过提供一个Map对象,以及泛型类型T

setDftLyr,通过lambda表达式的方式,配置Combox默认的选中值。

通过该扩展类, Combox.SelectedValue 即可获取该下拉框的选中对象

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using ArcGIS.Desktop.Mapping;

namespace GISCommonHelper
{
    public static class CartoLyrHelper
    {
        /// <summary>
        /// 设置图层
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cmb"></param>
        /// <param name="map"></param>
        public static void setLyrlist<T>(this ComboBox cmb,Map map) where T:Layer
        {
            var lyrlist = map.GetLayersAsFlattenedList().OfType<T>().ToList();
            List<Name_Layer> nlist = new List<Name_Layer>();
            lyrlist.ForEach(item =>
            {
                Layer l = (Layer)item;
                nlist.Add(new Name_Layer(l.Name, l));

            });
            cmb.ItemsSource = nlist;
            cmb.DisplayMemberPath = "Name";
            cmb.SelectedValuePath = "layer";
        }

        /// <summary>
        /// 设置下拉集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cmb"></param>
        /// <param name="map"></param>
        /// <param name="clause"></param>
        public static void setLyrlist<T>(this ComboBox cmb,Map map,Func<Layer,bool> clause) where T : Layer
        {
            cmb.setLyrlist<T>(map);
            cmb.setDftLyr(clause);
        }

        /// <summary>
        /// 设置默认选中的图层
        /// </summary>
        /// <param name="cmb"></param>
        /// <param name="clause"></param>
        public static void setDftLyr(this ComboBox cmb,Func<Layer,bool> clause)
        {
            List<Name_Layer>? lyrlist = new List<Name_Layer>();
            if (cmb.ItemsSource == null)
            {
                return;
            }
            else
            {
                lyrlist = cmb.ItemsSource as List<Name_Layer>;
            }
            for (int i = 0; i < lyrlist.Count; i++)
            {
                var item = lyrlist[i].layer;
                if (clause(item))
                {
                    cmb.SelectedIndex = i;
                }
            }
        }
    }

}

2.界面部分

ProWindow

XML 复制代码
<controls:ProWindow x:Class="DayDreamInGISTool.AttrSpecialStrRemove.RemoveAttrSpecialStrFrm"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:controls="clr-namespace:ArcGIS.Desktop.Framework.Controls;assembly=ArcGIS.Desktop.Framework"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:extensions="clr-namespace:ArcGIS.Desktop.Extensions;assembly=ArcGIS.Desktop.Extensions"
        mc:Ignorable="d" ResizeMode="NoResize"
        Title="移除属性中特殊字符" Height="300" Width="300"
        WindowStartupLocation="CenterOwner" Loaded="ProWindow_Loaded"
    >
    <controls:ProWindow.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <extensions:DesignOnlyResourceDictionary Source="pack://application:,,,/ArcGIS.Desktop.Framework;component\Themes\Default.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </controls:ProWindow.Resources>
    <Grid Name="RootGrid">
        <Label Content="图层" HorizontalAlignment="Left" Margin="12,8,0,0" VerticalAlignment="Top"/>
        <ComboBox Name="cmbLayer" HorizontalAlignment="Left" Margin="51,10,0,0" VerticalAlignment="Top" Width="229" SelectionChanged="cmbLayer_SelectionChanged"/>
        <GroupBox Header="待移除特殊字符" HorizontalAlignment="Left" Margin="12,41,0,0" VerticalAlignment="Top" Height="101" Width="268" Name="ToBeRemovedGroup">
            <Grid Height="90" Margin="0,0,0.2,-0.4" VerticalAlignment="Top">
                <CheckBox Name="chkEnter" IsChecked="True"  Content="换行符 \r\n" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
                <CheckBox Name="chkA" Content="响铃 \a" IsChecked="True" HorizontalAlignment="Left" Margin="142,10,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.313,0.526"/>
                <CheckBox Name="chkF" IsChecked="True"  Content="换页 \f" HorizontalAlignment="Left" Margin="10,34,0,0" VerticalAlignment="Top"/>
                <CheckBox Name="chkT" IsChecked="True"  Content="水平制表 \t" HorizontalAlignment="Left" Margin="142,34,0,0" VerticalAlignment="Top"/>
                <CheckBox Name="chkV" IsChecked="True"  Content="垂直制表 \v" HorizontalAlignment="Left" Margin="142,58,0,0" VerticalAlignment="Top" Checked="chkV_Checked"/>
                <CheckBox Name="chkStartEndSpace" IsChecked="True" Content="首尾空格符" HorizontalAlignment="Left" Margin="10,58,0,0" VerticalAlignment="Top"/>

            </Grid>
        </GroupBox>
        <Label Content="替换为" HorizontalAlignment="Left" Margin="12,151,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.155,0.477"/>
        <TextBox HorizontalAlignment="Left" Name="txtReplace" Height="23" Margin="64,151,0,0" TextWrapping="Wrap" Text="、" VerticalAlignment="Top" Width="216"/>
        <Button Content="确定" IsDefault="True" Name="btnOK" HorizontalAlignment="Left" Margin="49,220,0,0" VerticalAlignment="Top" Width="83" Height="30" Click="btnOK_Click"/>
        <Button Content="取消" IsCancel="True" Name="btnCancel" HorizontalAlignment="Left" Margin="174,220,0,0" VerticalAlignment="Top" Width="83" RenderTransformOrigin="-0.557,1.094" Height="30" Click="btnCancel_Click"/>
        <CheckBox Content="处理TOC中所有图层" Name="chkAll" HorizontalAlignment="Left" Margin="51,193,0,0" VerticalAlignment="Top"/>

    </Grid>
</controls:ProWindow>

下述代码为界面逻辑,主要实现交互获取,通过属性的方式

cs 复制代码
using ArcGIS.Desktop.Mapping;
using GISCommonHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DayDreamInGISTool.AttrSpecialStrRemove
{
    /// <summary>
    /// Interaction logic for RemoveAttrSpecialStrFrm.xaml
    /// </summary>
    public partial class RemoveAttrSpecialStrFrm : ArcGIS.Desktop.Framework.Controls.ProWindow
    {
        private FeatureLayer ftlyr = null;

        public FeatureLayer Ftlyr { get => ftlyr; set => ftlyr = value; }
        public char[] SpecialCharArray { get => specialCharArray; set => specialCharArray = value; }
        public bool IsAll { get => isAll; set => isAll = value; }
        public bool IsTrim { get => isTrim; set => isTrim = value; }
        public List<char> Special_char { get => special_char; set => special_char = value; }
        public string Replace_str { get => replace_str; set => replace_str = value; }

        private char[] specialCharArray;

        private bool isAll = false;

        private bool isTrim;

        private List<char> special_char;

        private string replace_str;

        public RemoveAttrSpecialStrFrm()
        {
            InitializeComponent();
            special_char = new List<char>();

            //获取所有图层
            var map = MapView.Active.Map;
            this.cmbLayer.setLyrlist<FeatureLayer>(map);
        }

        private void cmbLayer_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.cmbLayer.SelectedIndex >= 0)
            {
                this.ftlyr = this.cmbLayer.SelectedValue as FeatureLayer;
            }
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            replace_str = txtReplace.Text;
            isAll = chkAll.IsChecked.Value;

            if (chkA.IsChecked.Value)
            {
                special_char.Add('\a');
            }

            if (chkEnter.IsChecked.Value)
            {
                special_char.Add('\r');
                special_char.Add('\n');
            }

            if (chkF.IsChecked.Value)
            {
                special_char.Add('\f');
            }

            if (chkT.IsChecked.Value)
            {
                special_char.Add('\t');
            }

            if (chkV.IsChecked.Value)
            {
                special_char.Add('\v');
            }

            isTrim = chkStartEndSpace.IsChecked.Value;

            this.DialogResult = true;
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        private void chkV_Checked(object sender, RoutedEventArgs e)
        {

        }

        private void ProWindow_Loaded(object sender, RoutedEventArgs e)
        {
            
        }
    }
}

3.逻辑代码

cs 复制代码
using ArcGIS.Core.CIM;
using ArcGIS.Core.Data;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Catalog;
using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Editing;
using ArcGIS.Desktop.Extensions;
using ArcGIS.Desktop.Framework;
using ArcGIS.Desktop.Framework.Contracts;
using ArcGIS.Desktop.Framework.Dialogs;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Layouts;
using ArcGIS.Desktop.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DayDreamInGISTool.AttrSpecialStrRemove
{
    internal class btnRemoveAttrSpecialStr : Button
    {
        private List<char> special_char_list;
        private string replacestr = ";";
        private bool isTrim = false;
        int cnt = 0;

        RemoveAttrSpecialStrFrm rsf = null;

        protected override void OnClick()
        {
            rsf = new RemoveAttrSpecialStrFrm();
            if (rsf.ShowDialog().Value)
            {
                cnt = 0;
                special_char_list = rsf.Special_char;
                replacestr = rsf.Replace_str;
                isTrim = rsf.IsTrim;

                if (rsf.IsAll)
                {
                    var map = MapView.Active.Map;
                    var lyrlist= map.GetLayersAsFlattenedList().OfType<FeatureLayer>().ToList();
                    lyrlist.ForEach(p =>
                    {
                        Execute_specialStr_Remove(p);
                    });
                }
                else
                {
                    Execute_specialStr_Remove(rsf.Ftlyr);
                }
                
                MessageBox.Show("处理完成");
            }
        }

        /// <summary>
        /// 遍历要素,替换要素各字段中的特殊字符
        /// </summary>
        /// <param name="pftlyr"></param>
        /// <returns></returns>
        private async void Execute_specialStr_Remove(FeatureLayer pftlyr)
        {
            var fields = await QueuedTask.Run(() =>
            {
                return pftlyr.GetFieldDescriptions();
            });

            await QueuedTask.Run(() =>
            {
                using(Table table= pftlyr.GetTable())
                {
                    using(RowCursor rowCursor= table.Search(null, false))
                    {
                        while(rowCursor.MoveNext())
                        {
                            using(Row row= rowCursor.Current)
                            {
                                System.Diagnostics.Debug.WriteLine("正在处理:"+row.GetObjectID());
                                remove_feature_attr_specialStr(row,fields);
                            }
                        }
                    }
                }
            });

            //return cnt;
        }

        /// <summary>
        /// 替换要素所有字段中的特殊字符
        /// </summary>
        /// <param name="pFeature"></param>
        private void remove_feature_attr_specialStr(Row row,List<FieldDescription> fields)
        {
            for (int i = 0; i < fields.Count; i++)
            {
                FieldDescription pfd = fields[i];
                if (pfd.Type == FieldType.String)
                {
                    //只处理字符类型的值
                    string val = row[pfd.Name].ToString();
                    if(val!= null)
                    {
                        string val_r = remove_specialStrInString(val);
                        if (!string.Equals(val, val_r))
                        {
                            row[pfd.Name]= val_r;
                            row.Store();
                        }
                    }
                    
                }
            }
        }

        /// <summary>
        /// 替换字符串中的特殊字符
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string remove_specialStrInString(string str)
        {
            if (isTrim)
            {
                str = str.Trim();
            }

            special_char_list.ForEach(p =>
            {
                str = str.Replace(p.ToString(), replacestr);
            });

            return str;
        }
    }
}
相关推荐
规划GIS会7 个月前
【ArcGIS Pro二次开发】(84):WPF_给Combobox加点料
arcgis·c#·wpf·arcgis pro·arcgis pro 二次开发