ArcEngine的排序方法有多种,下面介绍一下主要的四种方法。

准备数据

测试数据如下图所示:新建一个Geodatabase的要素类,其中Name为道路名称,Width为道路宽度,下面将根据Width字段进行倒序排序。

ArcEngine实现要素类排序的四种方法_ArcEngine

方法一:IQueryFilterDefinition接口

利用IQueryFilterDefinition接口我们可以定义排序语句,代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;

namespace WindowsFormsApplication1
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            axMapControl1.LoadMxFile(@"E:\Users\dsf\Desktop\无标题.mxd");
        }

        private void btnSort_Click(object sender, EventArgs e)
        {
            IFeatureLayer pFeatureLayer = axMapControl1.get_Layer(0) as IFeatureLayer;
            DataTable dataTable = GetDataTable(pFeatureLayer.FeatureClass);
            dataGridView1.DataSource = dataTable;
        }

        private DataTable GetDataTable(IFeatureClass pFeatureClass)
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("OBJECTID");
            dataTable.Columns.Add("Name");
            dataTable.Columns.Add("Width");
            dataTable.Columns.Add("SHAPE_Length");

            // 字段索引
            int fieldIndex_OBJECTID = pFeatureClass.Fields.FindField("OBJECTID");
            int fieldIndex_Name = pFeatureClass.Fields.FindField("Name");
            int fieldIndex_Width = pFeatureClass.Fields.FindField("Width");
            int fieldIndex_SHAPE_Length = pFeatureClass.Fields.FindField("SHAPE_Length");

            // 字段排序
            IQueryFilter pQueryFilter = new QueryFilter();
            IQueryFilterDefinition pQueryFilterDefinition = pQueryFilter as IQueryFilterDefinition;
            pQueryFilterDefinition.PostfixClause = "order by Width desc";

            // 要素游标
            IFeatureCursor pFeatureCursor = pFeatureClass.Search(pQueryFilter, true);
            IFeature pFeature = pFeatureCursor.NextFeature();
            while (pFeature != null)
            {
                DataRow dataRow = dataTable.NewRow();
                dataRow[0] = pFeature.get_Value(fieldIndex_OBJECTID).ToString();
                dataRow[1] = pFeature.get_Value(fieldIndex_Name).ToString();
                dataRow[2] = pFeature.get_Value(fieldIndex_Width).ToString();
                dataRow[3] = pFeature.get_Value(fieldIndex_SHAPE_Length).ToString();
                dataTable.Rows.Add(dataRow);
                pFeature = pFeatureCursor.NextFeature();
            }

            // 释放游标
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatureCursor);
            return dataTable;
        }
    }
}

排序结果如下图所示:

ArcEngine实现要素类排序的四种方法_ArcEngine_02

方法二:IQueryDef2接口

利用IQueryDef2也可以实现排序功能,该接口只对Geodatabase的数据有效,不支持shp文件。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;

namespace WindowsFormsApplication1
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            axMapControl1.LoadMxFile(@"E:\Users\dsf\Desktop\无标题.mxd");
        }

        private void btnSort_Click(object sender, EventArgs e)
        {
            IFeatureLayer pFeatureLayer = axMapControl1.get_Layer(0) as IFeatureLayer;
            DataTable dataTable = GetDataTable(pFeatureLayer.FeatureClass);
            dataGridView1.DataSource = dataTable;
        }

        private DataTable GetDataTable(IFeatureClass pFeatureClass)
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("OBJECTID");
            dataTable.Columns.Add("Name");
            dataTable.Columns.Add("Width");
            dataTable.Columns.Add("SHAPE_Length");

            // 字段索引
            ITable pTable = pFeatureClass as ITable;
            int fieldIndex_OBJECTID = pTable.Fields.FindField("OBJECTID");
            int fieldIndex_Name = pTable.Fields.FindField("Name");
            int fieldIndex_Width = pTable.Fields.FindField("Width");
            int fieldIndex_SHAPE_Length = pTable.Fields.FindField("SHAPE_Length");

            // 获取工作空间
            IDataset pDataset = pFeatureClass as IDataset;
            IWorkspace pWorkspace = pDataset.Workspace;
            IFeatureWorkspace pFeatureWorkspace = pWorkspace as IFeatureWorkspace;

            // 字段排序
            IQueryDef2 pQueryDef = pFeatureWorkspace.CreateQueryDef() as IQueryDef2;
            pQueryDef.Tables = pFeatureClass.AliasName;
            pQueryDef.PostfixClause = "order by Width desc";

            // 要素游标
            ICursor pCursor = pQueryDef.Evaluate2(true);
            IRow pRow = pCursor.NextRow();
            while (pRow != null)
            {
                DataRow dataRow = dataTable.NewRow();
                dataRow[0] = pRow.get_Value(fieldIndex_OBJECTID).ToString();
                dataRow[1] = pRow.get_Value(fieldIndex_Name).ToString();
                dataRow[2] = pRow.get_Value(fieldIndex_Width).ToString();
                dataRow[3] = pRow.get_Value(fieldIndex_SHAPE_Length).ToString();
                dataTable.Rows.Add(dataRow);
                pRow = pCursor.NextRow();
            }

            // 释放游标
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pCursor);
            return dataTable;
        }
    }
}

排序结果如下图所示:

ArcEngine实现要素类排序的四种方法_ArcEngine_02

方法三:ITableSort接口

利用ITableSort接口也可以实现排序效果。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;

namespace WindowsFormsApplication1
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            axMapControl1.LoadMxFile(@"E:\Users\dsf\Desktop\无标题.mxd");
        }

        private void btnSort_Click(object sender, EventArgs e)
        {
            IFeatureLayer pFeatureLayer = axMapControl1.get_Layer(0) as IFeatureLayer;
            DataTable dataTable = GetDataTable(pFeatureLayer.FeatureClass);
            dataGridView1.DataSource = dataTable;
        }

        private DataTable GetDataTable(IFeatureClass pFeatureClass)
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("OBJECTID");
            dataTable.Columns.Add("Name");
            dataTable.Columns.Add("Width");
            dataTable.Columns.Add("SHAPE_Length");

            // 字段索引
            ITable pTable = pFeatureClass as ITable;
            int fieldIndex_OBJECTID = pTable.Fields.FindField("OBJECTID");
            int fieldIndex_Name = pTable.Fields.FindField("Name");
            int fieldIndex_Width = pTable.Fields.FindField("Width");
            int fieldIndex_SHAPE_Length = pTable.Fields.FindField("SHAPE_Length");

            // 字段排序
            ITableSort pTableSort = new TableSort();
            pTableSort.Table = pFeatureClass as ITable;
            pTableSort.Fields = "Width";
            pTableSort.set_Ascending("Width", false);
            pTableSort.Sort(null);

            // 要素游标
            ICursor pCursor = pTableSort.Rows;
            IRow pRow = pCursor.NextRow();
            while (pRow != null)
            {
                DataRow dataRow = dataTable.NewRow();
                dataRow[0] = pRow.get_Value(fieldIndex_OBJECTID).ToString();
                dataRow[1] = pRow.get_Value(fieldIndex_Name).ToString();
                dataRow[2] = pRow.get_Value(fieldIndex_Width).ToString();
                dataRow[3] = pRow.get_Value(fieldIndex_SHAPE_Length).ToString();
                dataTable.Rows.Add(dataRow);
                pRow = pCursor.NextRow();
            }

            // 释放游标
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pCursor);
            return dataTable;
        }
    }
}

排序结果如下图所示:

ArcEngine实现要素类排序的四种方法_ArcEngine_02

方法四:ITableSort + ITableSortCallBack实现自定义排序

很多情况下我们需要定义我们自己的排序规则,现在将数据表修改一下,如下图所示:Info字段记录了每条道路的名称和宽度,中间以"_"进行分隔。

ArcEngine实现要素类排序的四种方法_ArcEngine_05


现在我们希望只根据每条道路的宽度进行倒序排序,如果还是采用上述方法,你可能会得到这样的结果:

ArcEngine实现要素类排序的四种方法_System_06


很明显这不是我们想要的结果,不过还好ArcEngine给我们提供了一个ITableSortCallBack接口,利用这个接口我们可以自己定义排序规则,代码如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;

namespace WindowsFormsApplication1
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            axMapControl1.LoadMxFile(@"E:\Users\dsf\Desktop\无标题.mxd");
        }

        private void btnSort_Click(object sender, EventArgs e)
        {
            IFeatureLayer pFeatureLayer = axMapControl1.get_Layer(0) as IFeatureLayer;
            DataTable dataTable = GetDataTable(pFeatureLayer.FeatureClass);
            dataGridView1.DataSource = dataTable;
        }

        private DataTable GetDataTable(IFeatureClass pFeatureClass)
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("OBJECTID");
            dataTable.Columns.Add("SHAPE_Length");
            dataTable.Columns.Add("Info");

            // 字段索引
            ITable pTable = pFeatureClass as ITable;
            int fieldIndex_OBJECTID = pTable.Fields.FindField("OBJECTID");
            int fieldIndex_SHAPE_Length = pTable.Fields.FindField("SHAPE_Length");
            int fieldIndex_Info = pTable.Fields.FindField("Info");

            // 字段排序
            ITableSort pTableSort = new TableSort();
            pTableSort.Table = pFeatureClass as ITable;
            pTableSort.Compare = new CustomerSortRole();
            pTableSort.Fields = "Info";
            pTableSort.set_Ascending("Info", false);
            pTableSort.Sort(null);

            // 要素游标
            ICursor pCursor = pTableSort.Rows;
            IRow pRow = pCursor.NextRow();
            while (pRow != null)
            {
                DataRow dataRow = dataTable.NewRow();
                dataRow[0] = pRow.get_Value(fieldIndex_OBJECTID).ToString();
                dataRow[1] = pRow.get_Value(fieldIndex_SHAPE_Length).ToString();
                dataRow[2] = pRow.get_Value(fieldIndex_Info).ToString();
                dataTable.Rows.Add(dataRow);
                pRow = pCursor.NextRow();
            }

            // 释放游标
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pCursor);
            return dataTable;
        }
    }

    // 自定义排序规则
    public class CustomerSortRole : ITableSortCallBack
    {
        public int Compare(object value1, object value2, int FieldIndex, int fieldSortIndex)
        {
            double a = double.Parse(value1.ToString().Substring(value1.ToString().IndexOf("_") + 1));
            double b = double.Parse(value2.ToString().Substring(value2.ToString().IndexOf("_") + 1));
            if (a < b)
            {
                return -1;
            }
            else if (a == b)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
    }
}

排序结果如下图所示:

ArcEngine实现要素类排序的四种方法_Linq_07