在上一篇日志中介绍了自己通过几何的方法合并断开的线要素的ArcGIS插件式的应用程序。但是后来考虑到插件式的程序的配置和使用比较繁琐,也没有比较好的错误处理机制,于是我就把之前的程序封装成一个类似于ArcGIS中ArcToolBox中的批处理工具一样的程序,有输入文件的选择和输出文件的选择,类似于下面这个工具界面:

首先是查了一下ESRI的帮助文档ArcObjects Help for .NET,上面有关于如何创建自定义的Geoprocessing工具的几篇文章,介绍的不是很全面,但是可以知道创建工具的基本步骤和流程以及如何调试。下面创建自定义工具的基本步骤:

Creating a custom geoprocessing function tool 

There are, of course, scenarios for which you must create your own tool using ArcObjects. This requires implementing the IGPFunction2 and IGPFunctionFactory interfaces. The Building a custom geoprocessing function tool topic provides detailed information and examples. The following steps summarize the process:
  1. In a .NET application, create two classes (one will implement IGPFunction2 and the other will implement IGPFunctionFactory). You can create two separate files or keep them in a single file.
  2. Set the parameter properties (parameter type, direction, and acceptable values) in the ParameterInfo property of IGPFunction2.
  3. Leave the Validation method of IGPFunction2 as an empty stub—the geoprocessing framework automatically performs the validation.
  4. The Execute method of IGPFunction is the most important part of your tool. This is where you write your code to implement the specific algorithm.
  5. Implement IGPFunctionFactory. This makes your custom function tool accessible to users.

第一步需要创建两个类,分别实现IGPFunction2 和IGPFunctionFactory接口。在实现IGPFunction2 接口的类中定义Tool的目录、名称、输入参数、输出参数、进度条和Execute函数等参数。需要注意的是如果您的工具是有Output FeatureClass,那就需要在除了IArray ParameterInfo中设置输入、输出参数以外,还需在Execute函数中创建新的要素类作为输出要素类,并为其配置几何信息和字段信息:

 parameter = (IGPParameter)paramvalues.get_Element();
parameterValue = m_GPUtilities.UnpackGPValue(parameter);
Geoprocessor gp = new Geoprocessor();
// Create the new Output Polyline Feature Class
CreateFeatureclass cfc = new CreateFeatureclass(); //根据用户在output featureclass中命名的name创建新的输出要素
IName name = m_GPUtilities.CreateFeatureClassName(parameterValue.GetAsText());
IDatasetName dsName = name as IDatasetName;
IFeatureClassName fcName = dsName as IFeatureClassName;
IFeatureDatasetName fdsName = fcName.FeatureDatasetName as IFeatureDatasetName; // Check if output is in a FeatureDataset or not. Set the output path parameter for CreateFeatureClass tool.
if (fdsName != null)
{
cfc.out_path = fdsName;
}
else
{
cfc.out_path = dsName.WorkspaceName.PathName;
}
// Set the output Coordinate System for CreateFeatureClass tool.
IGPEnvironment env = envMgr.FindEnvironment("outputCoordinateSystem");
// Same as Input
if (env.Value.IsEmpty())
{
//IGeoDataset ds = inputFeatureClass as IGeoDataset;
//cfc.spatial_reference = ds.SpatialReference as ISpatialReference3;
}
// Use the evnviroment setting
else
{
IGPCoordinateSystem cs = env.Value as IGPCoordinateSystem;
cfc.spatial_reference = cs.SpatialReference as ISpatialReference3;
}
// Remaing properties for Create Feature Class Tool
cfc.out_name = dsName.Name;
cfc.geometry_type = "POLYLINE";
gp.Execute(cfc, null);

在配置好输入输出参数信息后,就可在Execute()函数中加上您自己的ArcEngine程序了,如果是WinForm或者ArcGIS插件式的AE程序,只需要修改参数,使程序的输入参数读取到的是在Tool中输入的input featureclass,输出参数是Tool中的output featureclass就可以了,最后程序的处理结果过自动加载到Arcmap地图窗口中进行显示。

在程序写完后,需要进行调试。这里进行调试和一般的ArcEngine程序不同,程序运行时不会直接命中VS中设置的断点,需要进行相关的配置才能进行正常的调试。在ESRI的帮助文档中有详细的介绍:

How to debug a function tool running in the background

Summary

This topic shows how to debug a function tool in Visual Studio in a background geoprocessing environment.

Debugging a function tool in background processing

When geoprocessing tools are run in ArcGIS applications, the user has the option to run them in a background process (personal server) instead of running them in ArcMap. For more information, see Foreground and background processing in the ArcGIS Desktop Help system.
When debugging a tool, attaching Visual Studio to the application (for example, ArcMap) will not trigger execution and validation break points since the code is not running in the application.
To debug tools, you can disable background processing or attach your debugger to the background process. To disable background processing, select Options under the application's Geoprocessing menu and clear the Run in background check box.

Debugging in the background

Complete the following steps to debug the tool in a background process:
  1. Start Visual Studio and open your tool project.
  2. When you run or build the .NET solution, it creates a dynamic-link library (DLL) that must be registered by the ESRIRegAsm utility. You can add a post-build command to automate the registration process. In the Project properties Build Events section, type the command on the post-build event command line. The following is one example of a post-build command to register with ArcGIS Engine:
"$(ProgramFiles)\Common Files\ArcGIS\bin\esriRegAsm.exe" $(TargetPath) /p:Engine /v:10.1 /s 
If debugging on ArcGIS for Desktop then set product to Desktop as /p:Desktop instead of /p:Engine
  1. Also, in the Project properties Debug section, set ArcMap in the Start external program option by browsing to the ArcMap.exe location. The default location is <Install Directory>\bin\ArcMap.exe.
  2. Set a breakpoint as necessary for debugging.
  3. Click Debug and click Start Debugging (or press F5) to run the project. The ArcMap application starts.
  4. From the ArcMap menu, click Geoprocessing > Geoprocessing Options. Confirm that Enabled is checked to ensure that background processing is enabled if you want to debug in the background, then click OK on the dialog box. This starts the background processes (if not already started).
  5. In Visual Studio, click Tools, then click Attach to Process. See the following screen shot:
  6. When you click Attach to Process, the Attach to Process dialog box appears. Under the Available Processes section, there will be two of the background processes (RuntimeLocalServer.exe). Select both of the processes and click Attach. See the following screen shot:

  7. In ArcMap, right-click the toolbox and select Add, then click Tool to add the function tool to a custom toolbox. The Add Tool dialog box appears. On the Add Tool dialog box, you can see your function tool under a toolbox named after the category you set in your code. See the following screen shot:
  8. Add the data to ArcMap (if not already added), and run your tool after populating the parameters.
  9. At the appropriate execution point, the debugging stops at the breakpoint.

按照以上步骤,附加上进程并注册了工具后,就可以设置断点进行调试了。不过需要注意的是这种进行调试的方法不太稳定——在完成一次调试后,重新打开VS运行程序后,在附加进程的对话框中再也找不到RuntimelocalServer.exe的两个进程,没有办法继续进行调试。刚开始自己也没有很好的解决办法,后来打电话到ESRI技术支持中心,他们那边的工程师在自己的电脑上调试这类程序也是这种情况说是一个bug,也没有很好的解决办法,只是说让我在winForm中把程序调通再改。后来就是尝试各种方法,一次在程序运行中尝试附加进程,结果终于看到了RuntimelocalServer.exe!!!

也就是说,遇到程序刚开始不能附加指定进程的情况,可以在已经在程序执行对话框这中配置好输入、输出参数后(程序已经在执行Execute()函数),再次在VS工具选项中尝试附加该进程,这时候就会正常命中断点!

最后程序调通后,就是Tool的注册和调用了。Tool的注册有两种方法,第一种是在VS中执行程序,Tool会自动注册到ArcGIS Desktop中;另一种方式是在程序编译后在程序目录的Debug文件夹找到.dll动态链接库文件,然后双击该文件,选择Desktop完成Tool在ArcGIS上的注册。

然后在ArcCatalog的自定义工具箱中找到Tool目录和对应工具,双击工具即可运行程序。我的Merge Disconnect Line工具运行后的参数配置界面如下:

在配置好输入参数和输出参数后,点击OK执行程序。

------------------------------------------------------------------------------------------------------------------------

本程序的主要代码:

 using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.DataManagementTools;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.Geoprocessor; namespace GPMergeDisconnectLine
{
/************************************************************************************************/
//定义GP工具
public class MergeDisjunctLineFunction : IGPFunction
{
//工具的名称
private string m_ToolName = "MergeDisconnectLine";
private string m_metadatafile = "MergeDisconnectLine.xml";
private IArray m_Parameters; // Array of Parameters
private IGPUtilities m_GPUtilities; public MergeDisjunctLineFunction()
{
m_GPUtilities = new GPUtilitiesClass();
} public string Name
{
get { return m_ToolName; }
} // Set the function tool Display Name as seen in ArcToolbox.
public string DisplayName
{
get { return "Merge Disconnect Line"; }
} public void Execute(IArray paramvalues, ITrackCancel trackcancel, IGPEnvironmentManager envMgr, IGPMessages message)
{
//输入参数
IGPParameter parameter = (IGPParameter)paramvalues.get_Element();
IGPValue parameterValue = m_GPUtilities.UnpackGPValue(parameter);
// Open Input Dataset
IFeatureClass inputFeatureClass = null;
IQueryFilter qf = null;
IGPRecordSet gprs = null;
IRecordSet2 rs2 = null; IFeatureClass outputFeatureClass = null;
int sumCount = ;
if (parameterValue.DataType is IDEGeoDatasetType)
{
m_GPUtilities.DecodeFeatureLayer(parameterValue, out inputFeatureClass, out qf);
if (inputFeatureClass == null)
{
message.AddError(, "Could not open input dataset.");
return;
}
sumCount = inputFeatureClass.FeatureCount(null);
}
else if (parameterValue.DataType is IGPFeatureRecordSetLayerType)
{
gprs = parameterValue as IGPRecordSet;
rs2 = gprs.RecordSet as IRecordSet2;
//SearchCursor = rs2.get_Cursor(false);
sumCount = rs2.Table.RowCount(null);
} /*Create FeatureClass 输出参数!!!*/
parameter = (IGPParameter)paramvalues.get_Element();
parameterValue = m_GPUtilities.UnpackGPValue(parameter);
Geoprocessor gp = new Geoprocessor();
// Create the new Output Polyline Feature Class
CreateFeatureclass cfc = new CreateFeatureclass(); //根据用户在output featureclass中命名的name创建新的输出要素
IName name = m_GPUtilities.CreateFeatureClassName(parameterValue.GetAsText());
IDatasetName dsName = name as IDatasetName;
IFeatureClassName fcName = dsName as IFeatureClassName;
IFeatureDatasetName fdsName = fcName.FeatureDatasetName as IFeatureDatasetName; // Check if output is in a FeatureDataset or not. Set the output path parameter for CreateFeatureClass tool.
if (fdsName != null)
{
cfc.out_path = fdsName;
}
else
{
cfc.out_path = dsName.WorkspaceName.PathName;
}
// Set the output Coordinate System for CreateFeatureClass tool.
IGPEnvironment env = envMgr.FindEnvironment("outputCoordinateSystem");
// Same as Input
if (env.Value.IsEmpty())
{
//IGeoDataset ds = inputFeatureClass as IGeoDataset;
//cfc.spatial_reference = ds.SpatialReference as ISpatialReference3;
}
// Use the evnviroment setting
else
{
IGPCoordinateSystem cs = env.Value as IGPCoordinateSystem;
cfc.spatial_reference = cs.SpatialReference as ISpatialReference3;
}
// Remaing properties for Create Feature Class Tool
cfc.out_name = dsName.Name;
cfc.geometry_type = "POLYLINE";
gp.Execute(cfc, null); outputFeatureClass = m_GPUtilities.OpenFeatureClassFromString(parameterValue.GetAsText());
//Set the properties of the Step Progressor
IStepProgressor pStepPro = (IStepProgressor)trackcancel;
pStepPro.MinRange = ;
pStepPro.MaxRange = ;
pStepPro.StepValue = ();
pStepPro.Message = "Merge disjunct polyline is in processing";
pStepPro.Position = ;
pStepPro.Show(); //合并操作开始
MergeOperation mOpetation = new MergeOperation();
pStepPro.Step();
List<IFeature> allPolylineList = mOpetation.getAllPolyline(inputFeatureClass);
pStepPro.Step();
List<IPoint> allNodePointList = mOpetation.GetNodePtsListByLine(allPolylineList);
pStepPro.Step();
List<IPoint> distinctNodePointList = mOpetation.GetDistinctNodePtsList(allNodePointList);
pStepPro.Step();
List<IFeature> unionLineList = mOpetation.MergeLineListOperate(allPolylineList, distinctNodePointList, inputFeatureClass);
pStepPro.Step();
mOpetation.AddField(inputFeatureClass, outputFeatureClass);
pStepPro.Step();
mOpetation.WriteUnionLineToFile(unionLineList, outputFeatureClass);
pStepPro.Step();
System.Runtime.InteropServices.Marshal.ReleaseComObject(outputFeatureClass);
//合并操作结束
pStepPro.Hide();
} // This is the location where the parameters to the Function Tool are defined.
// This property returns an IArray of parameter objects (IGPParameter).
// These objects define the characteristics of the input and output parameters.
public IArray ParameterInfo
{
get
{
//Array to the hold the parameters
IArray parameters = new ArrayClass(); IGPParameterEdit3 inputParameter = new GPParameterClass();
inputParameter.DataType = new GPFeatureLayerTypeClass();
inputParameter.Value = new GPFeatureLayerClass(); // Set Input Parameter properties
inputParameter.Direction = esriGPParameterDirection.esriGPParameterDirectionInput;
inputParameter.DisplayName = "Input Features";
inputParameter.Name = "input_features";
inputParameter.ParameterType = esriGPParameterType.esriGPParameterTypeRequired;
parameters.Add(inputParameter); // Output parameter (Derived) and data type is DEFeatureClass
IGPParameterEdit3 outputParameter = new GPParameterClass();
outputParameter.DataType = new DEFeatureClassTypeClass(); // Value object is DEFeatureClass
outputParameter.Value = new DEFeatureClassClass(); // Set output parameter properties
outputParameter.Direction = esriGPParameterDirection.esriGPParameterDirectionOutput;
outputParameter.DisplayName = "Output FeatureClass";
outputParameter.Name = "out_featureclass";
outputParameter.ParameterType = esriGPParameterType.esriGPParameterTypeRequired; // Create a new schema object - schema means the structure or design of the feature class (field information, geometry information, extent)
IGPFeatureSchema outputSchema = new GPFeatureSchemaClass();
IGPSchema schema = (IGPSchema)outputSchema; // Clone the schema from the dependency.
//This means update the output with the same schema as the input feature class (the dependency).
schema.CloneDependency = true; // Set the schema on the output because this tool will add an additional field.
outputParameter.Schema = outputSchema as IGPSchema;
outputParameter.AddDependency("input_features");
parameters.Add(outputParameter); return parameters;
}
} //验证合法性
public IGPMessages Validate(IArray paramvalues, bool updateValues, IGPEnvironmentManager envMgr)
{
if (m_Parameters == null)
m_Parameters = ParameterInfo;
if (updateValues)
{
//UpdateParameters(paramvalues, envMgr);
}
//// Call InternalValidate (Basic Validation). Are all the required parameters supplied?
//// Are the Values to the parameters the correct data type?
IGPMessages validateMsgs = m_GPUtilities.InternalValidate(m_Parameters, paramvalues, updateValues, true, envMgr); //UpdateMessages(paramvalues, envMgr, validateMsgs);
return validateMsgs;
} //更新参数,有些工具需要设置好一个参数后,才能设置下一个参数,例如需要选择一个矢量数据之后,
//才能选择数据中的字段,这样的工作可在该代码中定义,如何定义还需要查看帮助和示例
public void UpdateParameters(IArray paramvalues, IGPEnvironmentManager pEnvMgr)
{
//m_Parameters = paramvalues;
// Retrieve the input parameter value
//IGPValue parameterValue = m_GPUtilities.UnpackGPValue(m_Parameters.get_Element(0));
} // This is the function name object for the Geoprocessing Function Tool.
// This name object is created and returned by the Function Factory.
// The Function Factory must first be created before implementing this property.
public IName FullName
{
get
{
IGPFunctionFactory functionFactory = new MergeDisjunctLineFactory();
return (IName)functionFactory.GetFunctionName(m_ToolName);
}
} // This is used to set a custom renderer for the output of the Function Tool.
public object GetRenderer(IGPParameter pParam)
{
return null;
} //帮助的上下文标识 返回0即可
public int HelpContext
{
get { return ; }
} // This is the path to a .chm file which is used to describe and explain the function and its operation.
public string HelpFile
{
get { return ""; }
} // This is used to return whether the function tool is licensed to execute.
public bool IsLicensed()
{
IAoInitialize aoi = new AoInitializeClass();
ILicenseInformation licInfo = (ILicenseInformation)aoi;
string licName = licInfo.GetLicenseProductName(aoi.InitializedProduct());
if (licName == "Advanced")
{
return true;
}
else
{
return false;
}
} //元数据文件 这个返回空字符串也可以
public string MetadataFile
{
get
{
string filePath;
filePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
filePath = System.IO.Path.Combine(filePath, m_metadatafile);
return filePath;
}
} public UID DialogCLSID
{
// DO NOT USE. INTERNAL USE ONLY.
get { return null; }
}
} /*IGPFunctionFactory*************************************************************************************************/ [Guid("526de91e-3fe5-4a46-a7e2-4d1dc3cdb5db"), ComVisible(true)] public class MergeDisjunctLineFactory : IGPFunctionFactory
{
// Register the Function Factory with the ESRI Geoprocessor Function Factory Component Category. #region "Component Category Registration" [ComRegisterFunction()]
private static void Reg(string regKey)
{
GPFunctionFactories.Register(regKey);
} [ComUnregisterFunction()]
private static void Unreg(string regKey)
{
GPFunctionFactories.Unregister(regKey);
} #endregion // Utility Function added to create the function names.
private IGPFunctionName CreateGPFunctionNames(long index)
{
IGPFunctionName functionName = new GPFunctionNameClass();
functionName.MinimumProduct = esriProductCode.esriProductCodeAdvanced;
IGPName name; switch (index)
{
//工具箱中只有一个工具
case ():
name = (IGPName) functionName;
name.Category = "DisconnectlineMerge";
name.Description = "Merge a disconnect line list to a continuous line";
name.DisplayName = "Merge Disconnectline";
name.Name = "MergeDisconnectLine";
name.Factory = (IGPFunctionFactory) this;
break;
} return functionName;
} // Implementation of the Function Factory
// This is the name of the function factory.
// This is used when generating the Toolbox containing the function tools of the factory.
public string Name
{
get { return "DisconnectlineMerge"; }
} // This is the alias name of the factory.
public string Alias
{
get { return "lineMerge"; }
} // This is the class id of the factory.
public UID CLSID
{
get
{
UID id = new UIDClass();
id.Value = this.GetType().GUID.ToString("B");
return id;
}
} // This method will create and return a function object based upon the input name.
public IGPFunction GetFunction(string Name)
{
switch (Name)
{
case ("MergeDisconnectLine"):
IGPFunction gpFunction = new MergeDisjunctLineFunction();
return gpFunction;
} return null;
} // This method will create and return a function name object based upon the input name.
public IGPName GetFunctionName(string Name)
{
IGPName gpName = new GPFunctionNameClass(); switch (Name)
{
case ("MergeDisconnectLine"):
return (IGPName) CreateGPFunctionNames(); }
return null;
} // This method will create and return an enumeration of function names that the factory supports.
public IEnumGPName GetFunctionNames()
{
IArray nameArray = new EnumGPNameClass();
nameArray.Add(CreateGPFunctionNames());
return (IEnumGPName) nameArray;
} public IEnumGPEnvironment GetFunctionEnvironments()
{
return null;
}
}
}

本文是自己这几天做ArcGIS GP工具的一些心得体会,部分参考ESRI开发者中心文档。文章和代码如有不足之处,请和我联系,感谢!(邮箱:1312210561@qq.com)

-----------------------------------------------------------------------------------------------------

 本文系作者GISQZC原创文章,欢迎转载,但必须注明出处,否则将追究相关法律责任!

ArcGIS Engine环境下创建自定义的ArcToolbox Geoprocessing工具的更多相关文章

  1. windows环境下创建 .文件夹

    一.windows环境下创建 .文件夹 1.新建一个文件夹 2.重命名为.properties.(名字前后都加点) 二.windows环境下创建 .文件 1.上面的方法对文件同样适用 2.运行CMD, ...

  2. ROS 教程之 navigation :在 catkin 环境下创建costmap layer plugin

    在做机器人导航的时候,肯定见到过global_costmap和local_costmap.global_costmap是为了全局路径规划服务的,如从这个房间到那个房间该怎么走.local_costma ...

  3. centos环境下创建数据库和表的方法

    centos环境下创建数据库和表的方法 //查询数据库的命令: mysql> SHOW DATABASES; +--------------------+ | Database         ...

  4. [ArcGIS]Oracle RAC下创建地理数据库(Create Enterprise Geodatabase)失败的解决方法

    转载请注明原文地址:http://www.cnblogs.com/litou/p/8028843.html 环境:Oracle 11g 11.2.0.1.0(双节点RAC群集),ArcGIS Desk ...

  5. 在Windows中单机环境下创建RabbitMQ集群

    本文根据:http://www.360doc.com/content/15/0312/17/20874412_454622619.shtml整理而来 RabbitMQ具有很好的消息传递性能,同时又是开 ...

  6. 在linux下创建自定义service服务

    三个部分 这个脚本分为3个部分:[Unit] [Service] [Install]. Unit Unit表明该服务的描述,类型描述.我们称之为一个单元.比较典型的情况是单元A要求在单元B启动之后再启 ...

  7. linux环境下学习使用pro*c/c++工具

    1.proc是oracle用来预编译嵌入SQL语句的c程序. 2.如何使用proc工具 在Linux环境下,首先确保gcc编译器正常使用,安装oracle数据库或者客户端,一般就会默认安装pro*c/ ...

  8. 分享一个 Linux 环境下,强力的Python 小工具

    场景 Linux 用户,经常需要在终端查看一些数据,从文件里看 或者网络协议获取数据并查看. 比如,查看文件里的json数据:比如,查看etcd里存下的数据. 如果直接看cat 或者 curl 得到的 ...

  9. 多线程编程之Windows环境下创建新线程

    转自: http://www.cnblogs.com/lgxqf/archive/2009/02/10/1387480.html 在 Win32 API 中,创建线程的基本函数是 CreateThre ...

随机推荐

  1. 关于Unicode和URL encoding入门的一切以及注意事项

    本文同时也发表在我另一篇独立博客 <关于Unicode和URL encoding入门的一切以及注意事项>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了! ...

  2. 讲讲Handler+Looper+MessageQueue 关系

    Handler+Looper+MessageQueue这三者的关系其实就是Android的消息机制.这块内容相比开发人员都不陌生,在面试中,或者日常开发中都会碰到,今天就来讲这三者的关系. 概述: H ...

  3. Solr:文本分析

    文本分析时搜索引擎的核心工作之一,对文本包含许多处理步骤,比如:分词.大写转小写.词干化.同义词转化等.简单的说,文本分析就说将一个文本字段的值转为一个一个的token,然后被保存到Lucene的索引 ...

  4. CentOS 7添加yum源

    RedHat下主要有两个distribution,一曰 RHEL(Red Hat Enterprise Linux) 一曰 Fedora.前者主要是供服务器使用,优点是稳定,缺点是老的掉牙,后者是供桌 ...

  5. [SDK2.2]Windows Azure Virtual Network (2) 创建简单的Virtual Network

    <Windows Azure Platform 系列文章目录> 本章笔者将介绍如何创建一个简单的 Virtual Network. 1.首先我们登陆Windows Azure管理界面 ht ...

  6. Kibana源码剖析 —— savedSearch从读取到跳转

    持久化对象 Kibana中可以查询到很多保存的对象,他们都存储在es中一个叫做.kibana的索引中. 搜索 存储在type为search中; 图表 存储在type为visualization中: 仪 ...

  7. window、document、html、body、element的事件属性比较

    在分析jQuery的事件的时候有提到绑定事件的方式: Dean Edwards的跨浏览器事件绑定使用的方式是 element["on" + type] = handleEvent; ...

  8. 采用Kettle分页处理大数据量抽取任务

    作者:Grey 原文地址: http://greyzeng.com/2016/10/31/big-data-etl/ 需求: 将Oracle数据库中某张表历史数据导入MySQL的一张表里面. 源表(O ...

  9. 利用grunt-contrib-connect和grunt-connect-proxy搭建前后端分离的开发环境

    前后端分离这个词一点都不新鲜,完全的前后端分离在岗位协作方面,前端不写任何后台,后台不写任何页面,双方通过接口传递数据完成软件的各个功能实现.此种情况下,前后端的项目都独立开发和独立部署,在开发期间有 ...

  10. WinForm GDI+ 资料收集

    UI(User Interface)编程在整个项目开发过程中是个颇为重要的环节,任何好的解决方案若没有良好的用户界面呈现给最终用户,那么就算包含了最先进的技术也不能算是好程序.UI编程体现在两个方面, ...