图层可以作为图层文件(.lyrx)存在于地图或项目之外。图层文件是存储源数据集路径和其他图层特性(包括符号)的文件。这使得其他人可以轻松访问您构建的层。将图层文件添加到地图时,只要可以访问图层文件引用的数据,它将完全按照保存的方式绘制。
也可以将图层及其数据保存为图层包(.lpkx)。图层包包括图层特性和图层引用的数据集。使用图层包,您可以保存和共享有关图层的所有信息,包括符号、标签、表格特性和数据。其他用户可以直接将图层包添加到地图中,而无需知道如何访问数据库或对数据进行分类。
任何类型的图层都可以保存为图层文件或图层包,包括编组图层。请记住,图层文件仅包含对实际数据的引用。它不存储数据属性或几何体。
以下是将图层文件或包添加到地图的一些示例
// create a layer and add it to a groupLayer
string urlLyrx = @"\\Machine\SharedFolder\Census.lyrx";
Layer lyr = LayerFactory.Instance.CreateLayer(new Uri(urlLyrx), grpLayer)
// user the LayerCreationParams to customize the layer name
// KNOWN LIMIT – no other properties of the LayerCreationParams (or
// FeaturelayerCreationParams etc) will be honored when used
// with lyrx or lpkx files.
// This is a known limit at ArcGIS Pro 2.4
string urlLpkx = @"\\Machine\SharedFolder\Census.lpkx";
var createParams = new LayerCreationParams(new Uri(urlLpkx))
{
Name = "Population Density",
};
FeatureLayer flyr = LayerFactory.Instance.CreateLayer(createParams, myMap);
LayerDocument类提供了访问和修改图层文件内容的功能。使用此图案可以在将图层文件添加到地图之前更改图层文件特性。以下示例在将图层文件添加到地图之前更改图层文件的可见性和符号。
string urlLyrx = @"\\Machine\SharedFolder\Census.lyrx";
var layerDoc = new ArcGIS.Desktop.Mapping.LayerDocument(urlLyrx);
// get the CIMLayerDocument
var cimLayerDoc = layerDoc.GetCIMLayerDocument();
// manipulate the layer definitions
// change the visibility and renderer
var layerDefinitions = cimLayerDoc.LayerDefinitions;
var layerDef = layerDefinitions[0] as CIMFeatureLayer;
if (layerDef != null)
{
layerDef.Visibility = false;
layerDef.Renderer = new CIMSimpleRenderer()
{
Symbol = SymbolFactory.Instance.ConstructPolygonSymbol(
CIMColor.CreateRGBColor(255, 0, 0)).MakeSymbolReference()
};
}
// add it to the map
var createParams = new LayerCreationParams(cimLayerDoc);
LayerFactory.Instance.CreateLayer(createParams, MapView.Active.Map);
也可以使用LayerDocument类将图层文件中的符号应用于地图中的另一个图层,而无需将图层文件添加到地图中。
// default symbology
CIMRenderer renderer = new CIMSimpleRenderer()
{
Symbol = SymbolFactory.Instance.ConstructPolygonSymbol(
CIMColor.CreateRGBColor(255, 0, 0)).MakeSymbolReference()
};
// load the layer file into a LayerDocument
var layerDoc = new ArcGIS.Desktop.Mapping.LayerDocument(@"D:\Pro_SDK\LayerDocument\LANDUSE_polygon_Edit.lyrx");
var cimLayerDoc = layerDoc.GetCIMLayerDocument();
// retrieve the renderer from the LayerDocument
var layerDefinitions = cimLayerDoc.LayerDefinitions;
var layerDef = layerDefinitions[0] as CIMFeatureLayer;
if (layerDef != null)
{
renderer = layerDef.Renderer;
}
// apply the renderer to a layer in the map
// NOTE - the assumption is that the Landuse layer has the same fields
// as the layer file in order for the renderer to display correctly
var fLayer = MapView.Active.Map.GetLayersAsFlattenedList().
FirstOrDefault(l => l.Name == "Landuse") as FeatureLayer;
if (fLayer != null)
fLayer.SetRenderer(renderer);
FeatureLayers和StandaloneTables通常是访问和选择数据的入口点。这两个类都实现了IDisplayTable接口,以支持访问、查询和选择功能或行。
IDisplayTable还允许您获取字段列表、获取定义查询等。您还可以使用IsSelectable、SetSelectable、IsEditable和SetEditable方法获取和设置层或表的可选择性和可编辑性。请注意,(1)所有IDisplayTable成员都可以直接从FeatureLayer和StandaloneTable类获得,您不需要将它们强制转换到IDiplayTable接口,并且(2)这些方法在处理连接数据时可以正常工作。
要访问包含联接表的基表,需要使用GetTable方法。
还有一种搜索方法用于在图层或独立表格上执行搜索。此方法返回满足给定搜索条件的图层或独立表格中的要素或行的光标。如果存在定义查询集,则搜索将对满足定义条件的子集进行搜索。请注意,Search方法不适用于已连接字段和已连接字段返回的值;你不需要任何特别的东西。
//searching and returning number of features where value in 'Class' field in 'city'
QueryFilter qf = new QueryFilter()
{
WhereClause = "Class = 'city'"
};
using (RowCursor rows = aFeatureLayer.Search(qf))
{
int i = 0;
while (rows.MoveNext()) i++;
}
可以使用Select方法高亮显示地图视图或属性表窗口中的要素或行。
//selecting features in two layers where value in 'Class' field in 'city'
QueryFilter qf = new QueryFilter()
{
WhereClause = "Class = 'city'"
};
Selection selection = aFeatureLayer.Select(qf, SelectionCombinationMethod.New);
Selection selection2 = aFeatureLayer2.Select(qf, SelectionCombinationMethod.Add);
在2.x版本中像MapView.GetFeatures,MapView.GetFeaturesEx, MapView.SelectFeatures和MapView.SelectFeaturesEx的操作在MapView上返回了一组MapMembers,以及相应的对象ID列表,分别为Dictionary<BasicFeatureLayer,list>和Dictionary<Layer、list>。
2.x的公共API中的各种方法使用了返回的集合-例如MapView.ZoomTo(IReadOnlyDictionary<BasicFeatureLayer,List>,…)、MapView.PanTo(ireadOnly Dictionary
在3.0中,MapMembers和objectID的集合已被SelectionSet类替换。公共API中使用2.x集合的相应方法已更改为使用新的SelectionSet类。
对于那些使用LINQ过滤2.x处返回的集合Dictionary的加载项,SelectionSet类提供了ToDictionary转换方法。ToDictionary()将SelectionSet转换为LINQ字典集合,然后可以通过LINQ对其进行操作,操作方式与2.x相同。还有一个FromDictionary方法可以从集合集合创建SelectionSet。以下是一些示例:
QueuedTask.Run(() =>
{
var sel_poly = .... ;//Polygon to use for selection
// get the set of features intersecting sel_poly
// 2x returned Dictionary>
var selSet = MapView.Active.GetFeatures(sel_poly);
// convert to the dictionary
var selSetDict = selSet.ToDictionary();
// convert to the dictionary and only include those that are of type FeatureLayer
var selSetDict = selSet.ToDictionary();
//zoom to the extent of the retrieved set of features - No change
MapView.Active.ZoomTo(MapView.Active.GetFeatures(sel_poly));
//move the selected set of features - No change
var editOp = new EditOperation() { ..... };
editOp.Move(MapView.Active.SelectFeatures(sel_poly), 500.0, 500.0);
editOp.Execute();
//rotate - no change
var editOp = new EditOperation() { ..... };
editOp.Rotate(MapView.Active.SelectFeatures(sel_poly), origin, 35.0);
editOp.Execute();
//get the geometry of the first selected feature.
// Use ToDictionary() to apply LINQ
var selSet = MapView.Active.GetFeatures(sel_poly);
var selSetDict = selSet.ToDictionary();
var insp = new Inspector();
insp.Load(selSetDict.Keys.First(), selSetDict.Values.First());
var selGeom = insp.Shape;
//Get the list of object ids from SelectFeaturesEx for a particular layer.
// Use ToDictionary() to apply LINQ
var sname = "Points of Interest";
var selSet = MapView.Active.SelectFeaturesEx(env);
var oids1 = selSet.ToDictionary().Where(kvp => kvp.Key.Name == sname).First().Value;
//TODO - use the object ids
//Create a selection set from a list of object ids
//using FromDictionary
var addToSelection = new Dictionary>();
addToSelection.Add(us_zips, new List { 1506, 2696, 2246, 1647, 948 });
var sset = SelectionSet.FromDictionary(addToSelection);
//TODO - use sset
// get the objectIDs from mapMember in the features intersected by sel_poly
var selSet = MapView.Active.GetFeatures(sel_poly);
if (selSet.Contains(mapMember))
{
var oids = selSet[mapMember];
}
//etc
});
显示过滤器是与比例相关的查询,用于指定在地图上的比例范围绘制图层的哪些要素。显示过滤器非常适合与密集特征数据集一起使用,这些数据集具有大量以小比例绘制的特征。这会使数据难以直观地解释,并使层绘制缓慢。显示筛选器与定义查询的区别主要体现在以下两个方面:
可以使用CIMDisplayFilter(要素层CIM(制图信息模型)定义的一部分)创建并将显示过滤器应用于要素层。为要筛选的每个刻度范围创建一个CIMDisplayFilter。设置CIMDisplayFilter的MinScale和MaxScale属性以指定筛选器的缩放范围,并提供WhereClause来执行(功能)的实际筛选。显示筛选器比例范围不应重叠。
在下面的代码段中,定义了一个CIMDisplayFilters数组,指定了水文数据集在不同连续比例范围内显示的流速。显示过滤器以不同比例控制特征密度,而不会影响符号或底层特征:
//Create a list of Display Filters
var arrayDisplayFilters = new List()
{
new CIMDisplayFilter{ Name = "StreamOrder > 6",
WhereClause = "StreamOrder > 6", MinScale= 0, MaxScale=50000000},
new CIMDisplayFilter{ Name = "StreamOrder > 5",
WhereClause = "StreamOrder > 5", MinScale= 50000000, MaxScale=20000000},
new CIMDisplayFilter{ Name = "StreamOrder > 4",
WhereClause = "StreamOrder > 4", MinScale= 20000000, MaxScale=5000000},
new CIMDisplayFilter{ Name = "StreamOrder > 3",
WhereClause = "StreamOrder > 3", MinScale= 5000000, MaxScale=1000000},
new CIMDisplayFilter{ Name = "StreamOrder > 2",
WhereClause = "StreamOrder > 2", MinScale= 1000000, MaxScale=100000},
new CIMDisplayFilter{ Name = "StreamOrder > 1",
WhereClause = "StreamOrder > 1", MinScale= 100000, MaxScale=24000},
};
显示过滤器通过层CIM定义CIMFeatureLayer应用。DisplayFilters*集合属性。要使用显示筛选器,请使用层的CIMFeatureLayer。CIM定义上的EnableDisplayFilters属性必须设置为true。对CIM的更改应用于featureLayer.SetDefinition(…);完整的示例如下所示:
//Get the Hydrology layer from the TOC
var hydrologyLyr = MapView.Active.Map.FindLayers("Hydrology").First() as FeatureLayer;
await QueuedTask.Run(() =>
{
//Get the CIM Definition
var cimDefn = hydrologyLyr.GetDefinition() as CIMFeatureLayer;
//Create a list of Display Filters
var arrayDisplayFilters = new List()
{
new CIMDisplayFilter{ Name = "StreamOrder > 6",
WhereClause = "StreamOrder > 6", MinScale= 0, MaxScale=50000000},
new CIMDisplayFilter{ Name = "StreamOrder > 5",
WhereClause = "StreamOrder > 5", MinScale= 50000000, MaxScale=20000000},
new CIMDisplayFilter{ Name = "StreamOrder > 4",
WhereClause = "StreamOrder > 4", MinScale= 20000000, MaxScale=5000000},
new CIMDisplayFilter{ Name = "StreamOrder > 3",
WhereClause = "StreamOrder > 3", MinScale= 5000000, MaxScale=1000000},
new CIMDisplayFilter{ Name = "StreamOrder > 2",
WhereClause = "StreamOrder > 2", MinScale= 1000000, MaxScale=100000},
new CIMDisplayFilter{ Name = "StreamOrder > 1",
WhereClause = "StreamOrder > 1", MinScale= 100000, MaxScale=24000},
};
//apply the display filter collection to the CIM definition
cimDefn.DisplayFilters = arrayDisplayFilters.ToArray();
//make sure display filters are enabled
cimDefn.EnableDisplayFilters = true;
//apply the change to the CIM - note "filtered" features still show up in the attribute
//table view and are available for query and selection...
hydrologyLyr.SetDefinition(cimDefn);
});
CIMFeatureLayer.DisplayFilters 当EnableDisplayFilters为false时,可以为null。
要删除显示筛选器,请从层DisplayFilters集合中删除相关的CIMDisplayFilter。要关闭显示过滤器,请将EnableDisplayFilters属性设置为false。对CIM的任何更改必须始终通过SetDefinition(…)调用应用。
下面的屏幕截图显示了相同的美国水文数据集,来自上面的片段,以不同的比例范围绘制,并以流量表示,没有显示过滤器。请注意,要素密度会在小比例尺下模糊地图上的任何有意义的信息:
应用显示过滤器后,随着地图比例的变化(并“放大”),越来越多的要素将逐渐显示。在最小尺度下,仅显示流量最大的河流(“StreamOrder>6”):
在更大的比例尺下,相关显示过滤器的查询(针对“该”比例尺范围)允许绘制较小流量的河流,随着地图的“放大”(“StreamOrder>4”)逐渐增加到地图细节:
最后,在最大比例下,显示过滤器允许绘制所有要素,而不管其流量属性:
还提供了完整的“显示过滤器”示例:DisplayFilters示例
数据源需要修复或重定向到不同位置的原因有很多。在每个受影响的地图文档中手动进行这些更改的想法可能会让人难以接受。方法可用于Map、Layer和StandaloneTable类以编程方式进行这些更改。您可以控制更新单个地图成员的数据源,也可以同时更新具有公共工作空间的数据源。
FindAndReplaceWorkspacePath在Map、Layer和StandaloneTable类中可用,允许您用整个或部分字符串替换层或表的工作空间路径。如果工作区类型或数据集名称已更改,则无法使用它。它非常适合驱动器号更改、切换到UNC路径、更新SDE连接文件信息等情况。
ReplaceDatasource(也在Map、Layer和StandaloneTable类上)允许您更改共享工作空间路径的所有层和表的整个工作空间路径。
Map类还提供ChangeVersion方法来切换和查看来自不同地理数据库版本的数据。
ArcGIS Pro使用缓存来优化在以前访问的区段中工作时的性能。当对地图、图层特性或其中的数据进行更改时(例如编辑地图中的要素时),将刷新此缓存。这称为显示缓存。在大多数情况下,可以将缓存选项设置为频繁使缓存无效,或者根本不使用缓存。DisplayCacheType属性控制每个层的此设置。
对于web要素图层,要素缓存用于通过将要素存储在临时文件夹中来提高性能和常见任务。缓存是自动管理的,并且随着功能的缓存,检索数据所需的查询数量会减少,绘图时间也会缩短。当使用大型或复杂的数据集时,在特定的地图范围内,或者当许多用户使用相同的服务时,这可能非常有用。这也减少了服务器的压力,因为它减少了服务请求的数量。FeatureCacheType属性控制层是否参与要素缓存的设置。只有某些类型的层(BasicFeatureLayer、SubtypeGroupLayer)支持FeatureCacheType属性。
可以使用SetCacheOptions更新层的缓存选项。如果图层的要素类支持要素缓存,则同时设置显示缓存和要素缓存,否则仅设置显示缓存。下表显示了LayerCacheType与DisplayCacheType和FeatureCacheType枚举之间的映射。
下面是显示SetCacheOptions方法的代码片段。
DisplayCacheType currentDCT = featureLayer.DisplayCacheType;
FeatureCacheType currentFCT = featureLayer.FeatureCacheType;
await QueuedTask.Run(() =>
{
featureLayer.SetCacheOptions(LayerCacheType.None);
});
默认情况下,功能缓存由应用程序自动填充。但是,您可以手动管理缓存,以利用缓存提供的性能优势。使用AutoFillFeatureCache和SetAutoFillfeatureCafe例程控制此设置。
必须先填充功能缓存才能使用。您可以选择为整个地图(仅适用于地图中的web要素图层)或指定的图层集填充缓存。此处概述了为层填充缓存的规则。请注意,层的FeatureCacheType必须设置为FeatureCacheType。为该层生成的功能缓存的会话(以及满足其他规则)。
在调用FillFeatureCacheAsync方法之一之前,使用CanFillFeetureCache方法确定应用程序当前是否正在满足现有的填充缓存请求。如果应用程序在调用时正在满足现有的填充缓存请求,FillFeatureCacheAsync方法将抛出InvalidOperationException。因此,建议将缓存方法包装在try/catch中。使用showToast参数表示在执行操作期间是否在应用程序中显示toast通知。
var map = MapView.Active.Map;
if (map.CanFillFeatureCache())
{
var msg = await QueuedTask.Run(() =>
{
try
{
map.FillFeatureCacheAsync(showToast);
// or specify a set of web feature layers
// map.FillFeatureCacheAsync(layers, showToast);
return "";
}
catch (Exception ex)
{
return ex.Message;
}
});
}
使用ClearFeatureCacheAsync方法清除功能缓存。与填充方法一样,可以清除地图中整个web要素图层集(要素服务)或图层子集的缓存。
var msg = await QueuedTask.Run(async () =>
{
try
{
await MapView.Active.Map.ClearFeatureCacheAsync(showToast);
//or a set of layers
// await MapView.Active.Map.ClearFeatureCacheAsync(layers, showToast);
return "";
}
catch (Exception ex)
{
return ex.Message;
}
});
您可以通过CancelFeatureCacheRequestsAsync方法取消任何现有的缓存请求。
var msg = await QueuedTask.Run(() =>
{
try
{
MapView.Active.Map.CancelFeatureCacheRequestsAsync(showToast);
return "";
}
catch (Exception ex)
{
return ex.Message;
}
});
FeatureCacheEvent提供执行功能缓存操作时的信息。如果您希望得到通知,请订阅此活动。例如,以下片段将允许您在缓存操作开始、完成、取消等时显示自己的toast通知消息。使用FeatureCacheEventArgs.EventHint确定事件提示。
FeatureCacheEvent.Subscribe(OnFeatureCacheHint);
...
internal void OnFeatureCacheHint(FeatureCacheEventArgs args)
{
_ = ArcGIS.Desktop.Internal.Mapping.Utilities.StartOnUIThread(() =>
{
string msg = "";
switch (args.EventHint)
{
case FeatureCacheEventHint.NoLayers:
msg = "There are no layers to cache";
break;
case FeatureCacheEventHint.Started:
msg = "Cache Fill operation started";
break;
case FeatureCacheEventHint.Completed:
msg = "Cache fill operation completed";
break;
case FeatureCacheEventHint.Clear_Started:
msg = "Cache clear operation started";
break;
case FeatureCacheEventHint.Clear_Completed:
msg = "Cache clear operation completed";
break;
case FeatureCacheEventHint.Canceled:
msg = "Cache Fill operation canceled";
break;
case FeatureCacheEventHint.Error:
msg = "An error in the cache operation.";
break;
}
Notification toast = new Notification
{
Title = "My notification",
Message = msg,
};
toast.ImageSource = BitmapUtil.GetImageSource(
"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/Success_Toast48.png");
FrameworkApplication.AddNotification(toast);
});
}
样式是包含符号、颜色、配色方案和布局元素等可重用内容的项目项。它们由StyleProjectItem类表示。可以按如下方式检索项目中的样式:
//Get all styles in the project
var styles = Project.Current.GetItems();
//Get a specific style in the project
StyleProjectItem style = styles.First(x => x.Name == "NameOfTheStyle");
ArcGIS Pro包括已安装并可添加到项目中的系统样式。这些是只读的;您不能修改它们的内容。创建新项目时,将向项目中添加四种系统样式(ArcGIS 2D、ArcGIS 3D、ArcGIS Colors和ColorBrewer Schemes RGB),以确保多功能符号、颜色、颜色方案和布局元素的库。
除了系统样式之外,还可以创建新的自定义样式,并将其添加到项目中,如下所示:
//Full path for the new style file (.stylx) to be created and added to the project
string styleToCreate = @"C:\Temp\NewStyle.stylx";
Project.Current.CreateStyle(styleToCreate);
或者,如果样式文件已经存在,请使用以下命令将新样式(系统或自定义)添加到项目中。
//For ArcGIS Pro system styles, just pass in the name of the style to add to the project
Project.Current.AddStyle("3D Vehicles");
//For custom styles, pass in the full path to the style file on disk
string customStyleToAdd = @"C:\Temp\CustomStyle.stylx";
Project.Current.AddStyle(customStyleToAdd);
从项目中删除样式不会删除或更改样式或其内容。可以从项目中删除样式,如下所示:
//For core ArcGIS Pro styles, just pass in the name of the style to remove from the project
Project.Current.RemoveStyle("3D Vehicles");
//For custom styles, pass in the full path to the style file on disk
string customStyleToRemove = @"C:\Temp\CustomStyle.stylx";
Project.Current.RemoveStyle(customStyleToRemove);
除了4种系统样式外,每个新项目中还添加了“收藏夹”样式。默认情况下,此样式为空。但是,可以使用AddItem(…)通过UI或公共API将样式项添加到“收藏夹”中。访问收藏夹样式与访问其中一个系统样式略有不同,因为它不存储在项目项集合中。相反,它存储在Style容器的项集合中,并在项目打开时(如果这是一个新项目,则正在创建)进行配置。要访问收藏夹样式,请使用以下代码段:
//note: we must be on the MCT to call "GetItems" on the style container
var fav_style_item = await QueuedTask.Run(() =>
{
var style_container = Project.Current.GetProjectItemContainer("Style");
return style_container.GetItems().OfType().First(item => item.TypeID == "personal_style");
});
if (fav_style_item != null)
{
...
}
符号和样式的底层结构可能会随着ArcGIS Pro的相继发布而改变。这意味着在早期版本中创建的样式可能不是最新的。非当前样式仍可以在项目中使用,但将是只读的。可以按如下方式检查样式是否为当前样式:
//For custom styles, pass in the full path to the style file on disk
string customStyleToAdd = @"C:\Temp\CustomStyle.stylx";
Project.Current.AddStyle(customStyleToAdd);
StyleProjectItem style = Project.Current.GetItems().First(x => x.Path == customStyleToAdd);
//returns true if style matches the current Pro version
bool isCurrent = style.IsCurrent;
如果样式不是当前样式,则可以对其进行升级。升级将允许您添加、删除和修改样式的内容。
//For custom styles, pass in the full path to the style file on disk
string customStyleToAdd = @"C:\Temp\CustomStyle.stylx";
Project.Current.AddStyle(customStyleToAdd);
StyleProjectItem style = Project.Current.GetItems().First(x => x.Path == customStyleToAdd);
//Upgrade style
if (style.CanUpgrade)
{
StyleHelper.UpgradeStyle(style);
}
StyleItem表示样式中包含的项。样式可以包含以下类型的样式项:
SymbolStyleItem可以是以下类型:
//Get all point symbols in a style - pass in an empty string for the searchString parameter
IList allPointSymbols = style.SearchSymbols(StyleItemType.PointSymbol, "");
//Get point symbols in a style that satisfy the search criteria
IList pointSymbols = style.SearchSymbols(StyleItemType.PointSymbol, "red");
同样,您也可以搜索其他类型的样式项。例如,以下是如何搜索样式中的颜色:
//Get colors in a style that satisfy the search criteria
IList colors = style.SearchColors("blue");
样式中的每个样式项都有一个唯一的键,该键可用于从样式中检索特定的样式项,如下所示:
//Get a specific style item from a style based on the KEY of the style item
//In this example, "Cone_Volume_3" is the KEY of the Cone symbol in the "ArcGIS 3D" system style
SymbolStyleItem redCone = await QueuedTask.Run(() =>
{
return style.LookupItem(StyleItemType.PointSymbol, "Cone_Volume_3") as SymbolStyleItem;
});
可以按如下方式添加样式项或从样式中删除样式项:
//Add a style item to a style
await QueuedTask.Run(() =>
{
style.AddItem(styleItemToAdd);
});
//Remove a style item from a style
await QueuedTask.Run(() =>
{
style.RemoveItem(styleItemToRemove);
});
一旦你有了StyleItem,就很容易检索它的内容。例如,从SymbolStyleItem中检索符号,如下所示:
//Get symbol from SymbolStyleItem
CIMSymbol symbol = await QueuedTask.Run(() =>
{
return symbolStyleItem.Symbol;
});
类似地,您可以从各自的样式项中检索颜色、颜色渐变、指北针等。例如,这是如何从NorthArrowStyleItem检索指北针的:
//Get north arrow from NorthArrowStyleItem
CIMNorthArrow northArrow = await QueuedTask.Run(() =>
{
return northArrowItem.NorthArrow;
});
StyleItem类旨在支持数据绑定,这有助于创建自定义符号库。可以根据搜索条件从样式中检索样式项,结果可以与库中每个样式项的预览图像一起显示。CustomSymbolPicker SDK示例显示了如何实现这一点。
SymbolFactory.Instance提供了许多静态方法和属性来创建新符号。例如,可以按如下方式创建新符号:
//Construct a point symbol of a specific color, size and shape
CIMPointSymbol pointSymbol = await QueuedTask.Run(() =>
{
return SymbolFactory.Instance.ConstructPointSymbol(
ColorFactory.Instance.RedRGB, 10.0, SimpleMarkerStyle.Star);
});
//Construct a polygon symbol of specific color and fill style
CIMPolygonSymbol polygonSymbol =
SymbolFactory.Instance.ConstructPolygonSymbol(ColorFactory.Instance.RedRGB, SimpleFillStyle.Solid);
//Construct a line symbol of specific color, size and line style
CIMLineSymbol lineSymbol =
SymbolFactory.Instance.ConstructLineSymbol(ColorFactory.Instance.BlueRGB, 4.0, SimpleLineStyle.Solid);
还提供了用于编辑符号的某些属性的方法。例如:
//Set rotation of point symbol
pointSymbol.SetAngle(30.0);
//Set width of line symbol
lineSymbol.SetSize(4.0);
在3D场景中,点、线和多边形符号可以以真实世界单位或页面单位显示。如果符号以真实单位显示,则符号将随距离缩放,这意味着当您放大符号时,符号将显示得更大,而当您远离符号时,则符号会显示得更小。创建新符号时,必须将符号的实际单位设置设置为与要素图层的单位设置相同,以便不会因为不匹配而看到意外的显示结果。这是如何做到的:
//Set real world setting of symbol to be the same as that of the feature layer
pointSymbol.SetRealWorldUnits(featureLayer.UsesRealWorldSymbolSizes);
要更新要素层的符号,首先需要通过调用GetRenderer方法获取要素层的当前渲染器,将渲染器的符号引用设置为新符号的符号引用,然后通过调用SetRenderer法更新要素层渲染器。例如,以下是如何为使用简单渲染器符号化的要素层更新符号:
//Get simple renderer from the feature layer
CIMSimpleRenderer currentRenderer = featureLayer.GetRenderer() as CIMSimpleRenderer;
//Set the symbol's real world setting to be the same as that of the feature layer
symbolToApply.SetRealWorldUnits(featureLayer.UsesRealWorldSymbolSizes);
//Update the symbol reference of the current simple renderer
currentRenderer.Symbol = symbolToApply.MakeSymbolReference();
//Update the feature layer renderer
featureLayer.SetRenderer(currentRenderer);
您可以将全球导航设备(如GNSS接收器)连接到ArcGIS Pro,以查看地图或场景中的当前位置。GNSS或全球导航卫星系统是用于提供具有全球覆盖范围的自主地理空间定位的卫星导航系统的标准通用术语。设备位置API允许您连接、可视化和访问连接的GNSS设备的数据。
要将GNSS设备连接到Pro,它必须支持国家海洋电子协会(NMEA)语句形式的输出。加载项将使用ArcGIS.Desktop.Core.DeviceLocation.DeviceLocationService。实例singleton以打开、关闭和更新与GNSS设备的连接。多个GNSS设备可以连接到一台机器,但是,只能将一个设备设置为当前活动或“打开”连接。若要打开连接,外接程序必须指定DeviceLocationSource以及任何关联的DeviceLocation属性(可选)。当前,SerialPortDeviceLocationSource源对象仅支持一个设备位置源。
至少,必须指定设备位置源连接到的ComPort。如果未指定空间参考,则假定为WGS84。如果未指定波特率,则假定为4800。如有必要,可使用DeviceLocationProperties参数设置AccuracyThreshold。
var newSrc = new SerialPortDeviceLocationSource();
newSrc.ComPort = "Com3";//required
newSrc.BaudRate = 4800; //optional
newSrc.AntennaHeight = 3; // meters
//Sr WGS84 will be assumed
var props = new DeviceLocationProperties();
props.AccuracyThreshold = 10; // meters
try
{
// jump to the background thread
await QueuedTask.Run(() =>
{
// open the source
DeviceLocationService.Instance.Open(newSrc, props);
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
外接程序可以调用DeviceLocationService.Instance。IsDeviceConnected()确定源当前是否已连接,以及DeviceLocationService.Instance。GetSource()检索其连接参数。
if (DeviceLocationService.Instance.IsDeviceConnected())
{
var src = DeviceLocationService.Instance.GetSource();
//Get the connection source properties
if (src is SerialPortDeviceLocationSource serialPortSrc)
{
var port = serialPortSrc.ComPort;
... //etc
外接程序可以通过调用DeviceLocationService.Instance.Close()从当前GNSS关闭。
await QueuedTask.Run(() =>
{
//If no device is connected, close is a no-op
DeviceLocationService.Instance.Close();
});
可以通过DeviceLocationSource.Instance检索当前快照数据。GetCurrentSnapshot()方法。快照类型为NMEASnapshot;用于表示来自符合NMEA规范的设备的馈送的数据结构。
在以下片段中,将检索最新快照并将其添加到图形层:
// ensure there is a device
var source = DeviceLocationService.Instance.GetSource();
if (source == null)
return;
bool validPoint = await QueuedTask.Run(() =>
{
// get the last location
var snapshot = DeviceLocationService.Instance.GetCurrentSnapshot();
var pt = snapshot?.GetPositionAsMapPoint();
if ((pt == null) || (pt.IsEmpty))
return false;
// create symbol
var ptSymbol = SymbolFactory.Instance.ConstructPointSymbol(
CIMColor.CreateRGBColor(125, 125, 0), 10, SimpleMarkerStyle.Triangle);
// Add it to the graphics layer
graphicsLayer.AddElement(pt, ptSymbol);
graphicsLayer.ClearSelection();
return true;
});
除了当前快照,外接程序还可以订阅SnapshotChangedEvent(在ArcGIS.Desktop.Core.DeviceLocation.Events命名空间中)。每次(从打开的设备)接收到新快照时,都会引发此事件。
SnapshotChangedEvent.Subscribe(OnSnapshotChanged)
private void OnSnapshotChanged(SnapshotChangedEventArgs args)
{
if (args == null)
return;
var snapshot = args.Snapshot as NMEASnapshot;
if (snapshot == null)
return;
QueuedTask.Run(() =>
{
var pt = snapshot.GetPositionAsMapPoint();
// examine properties of MMEASnapshot
// snapShot.DateTime, snapshot.Altitiude
// snapshot.Latitude, snapshot.Longitude
// snapshot.VDOP etc
//TODO - use returned point
});
}
注意:使用编辑API EditOperation.Create创建具有当前设备位置坐标的特征。
要开始跟踪活动视图上的位置更新或“快照”,必须启用打开的设备位置源(在当前地图上)。外接程序通过MapDeviceLocationService启用(和禁用)开放设备位置源。实例调用MapDeviceLocationService.Instance的单个对象。SetDeviceLocationEnabled(true | false)。在启用设备位置源之前,外接程序应检查是否存在活动视图和映射以及是否存在打开的设备位置源,否则将引发InvalidOperationException。
//Enable the current device location source...
//There must be an active map or an InvalidOperationException will be thrown
if (MapView.Active?.Map == null)
return;
//There must be an open device location source or an InvalidOperationException will be thrown
if (!DeviceLocationService.Instance.IsDeviceConnected())
return;
//Enable the device
QueuedTask.Run(() => MapDeviceLocationService.Instance.SetDeviceLocationEnabled(true));
一旦在当前地图上启用了设备位置源,就可以通过MapDeviceLocationService.Instance.SetDeviceLocaationOptions(选项)在地图上设置与如何跟踪快照相关的各种选项。根据MapDeviceLocationOptions的配置方式,地图将自动跟踪传入的位置快照(一旦启用)。地图也可以通过MapDeviceLocationService.Instance显式平移或缩放到最近的快照。ZoomOrPanToCurrentLocation(true|false)分别缩放或平移。在未启用设备位置源的情况下调用SetDeviceLocationOptions或ZoomOrPanToCurrentLocation将引发InvalidOperationException。
配置当前源的显示,然后缩放到当前快照位置,如下图所示:
//There must be an active map or an InvalidOperationException will be thrown
if (MapView.Active?.Map == null)
return;
//There must be an open device location source or an InvalidOperationException will be thrown
if (!DeviceLocationService.Instance.IsDeviceConnected())
return;
//Get the current options
var options = MapDeviceLocationService.Instance.GetDeviceLocationOptions();
//Configure...
options.DeviceLocationVisibility = true; // show the device location
options.NavigationMode = MappingDeviceLocationNavigationMode.KeepAtCenter;
options.TrackUpNavigation = true;;
// update the options
QueuedTask.Run(() =>
{
MapDeviceLocationService.Instance.SetDeviceLocationOptions(options);
//zoom to the most recent snapshot location
MapDeviceLocationService.Instance.ZoomOrPanToCurrentLocation(true);
});
在地图视图的底部可以找到许多标准地图托盘按钮(捕捉、栅格、约束、推断、更正)。可视地图托盘按钮的数量可根据视图类型(2D、3D场景等)进行配置。下面的屏幕截图显示了二维地图的托盘按钮区域和标准地图托盘按钮。
在3.0版本中,有一个VisualStudio模板(ArcGIS Pro地图托盘按钮),允许您创建自己的自定义地图托盘按钮。地图托盘按钮在配置的esri_mapping_MapTrayButtons类别中定义并注册。daml文件。
<updateCategory refID="esri_mapping_MapTrayButtons">
<insertComponent id="TrayButtons_MyTrayButton" className="MyTrayButton">
<content L_name="My TrayButton"
largeImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonRed32.png"
smallImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonRed16.png"
L_tooltipHeading="My TrayButton" L_tooltip="This is a sample tray button">content>
insertComponent>
每个Map Tray Button类都继承自MapTrayButton,并具有可设置为Button、ToggleButton或PopupToggle按钮的ButtonType属性。每种按钮类型都允许不同的可配置行为。当ButtonType为Button时,设置ClickCommand属性以在单击按钮时执行某些操作。如果ButtonType为ToggleButton或PopupToggle按钮,则重写OnButtonChecked方法以配置按钮状态更改时的行为。重写ConstructPopupContent方法,以在按钮悬停且ButtonType为PopupToggleButton时提供要显示的用户界面。
可以使用配置中的placeWith和insert属性定位自定义托盘按钮。daml文件。您还可以通过添加分隔符属性并将其设置为true,在托盘按钮之前添加分隔符。
<updateCategory refID="esri_mapping_MapTrayButtons">
<insertComponent id="TrayButtons_MyTrayButton" className="MyTrayButton">
<content L_name="My TrayButton"
largeImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonRed32.png"
smallImage="pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericButtonRed16.png"
placeWith="esri_mapping_SnappingTrayButton" insert="before"
L_tooltipHeading="My TrayButton" L_tooltip="This is a sample tray button">content>
insertComponent>
此图显示了包含2个自定义地图托盘按钮的地图托盘区域,其中一个按钮插入在“捕捉”之前,另一个按钮(PopupToggleButton类型)前面带有分隔符。
覆盖IsVisibleOnView以根据视图类型或其他场景自定义托盘按钮的可见性。
public override bool IsVisibleOnView()
{
return Is2DMap;
// another example
// show the tray button only when the map name is "MyMap"
// return (this.MapView?.Map?.Name == "MyMap");
}
MapTrayButton示例用于说明可用的不同地图托盘按钮。ProGuide MapTrayButton提供了附加文档,并随附示例。
坐标系选择器是一个UI组件,类似于ArcGIS Pro Map属性页上的核心坐标选择器。在外接程序中使用此选项,允许用户选择空间参照。使用CoordinateSystemControlProperties对象配置控件
xmlns:mapping="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<Border BorderBrush="{DynamicResource Esri_BorderBrush}" BorderThickness="2" Margin="2">
<mapping:CoordinateSystemsControl x:Name="CoordinateSystemsControl"
ConfigureControl="{Binding Path=ControlProperties}"/>
Border>
“坐标系详细信息”控件显示指定空间参照的特性。它可以与坐标系选择器结合使用,后者提供用于选择空间参考的UI,也可以单独使用。
xmlns:mapping="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<mapping:CoordinateSystemsDetailsControl
SpatialReference="{Binding ElementName=CoordinateSystemsControl, Path=SelectedSpatialReference}"
ShowVerticalCSDetails="true"/>
可以在“坐标系”对话框中找到使用“坐标系选择器”和“坐标系详细信息”控件的示例。
要将“符号搜索器控件”添加到外接程序DockPane并使其以独立方式运行,请将以下代码段添加到视图(XAML)中。
xmlns:controls="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<StackPanel Orientation="Vertical">
<controls:SymbolSearcherControl x:Name="SymbolSearch"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"/>
<ListBox x:Name="SymbolPicker"
ItemsSource="{Binding Path=SearchResultStyleItems, ElementName=SymbolSearch, Mode=OneWay}"
SelectedItem="{Binding SelectedPickerStyleItem}"
DisplayMemberPath="Name"
HorizontalAlignment="Stretch"
VerticalAlignment="Top" MaxHeight="450"/>
StackPanel>
并将相应的属性添加到ViewModel类中:
using ArcGIS.Desktop.Mapping;
using ArcGIS.Desktop.Mapping.Controls;
private StyleItem _selectedPickerStyleItem;
public StyleItem SelectedPickerStyleItem
{
get => _selectedPickerStyleItem;
set
{
SetProperty(ref _selectedPickerStyleItem, value);
MessageBox.Show($@"SelectedPickerStyleItem: {_selectedPickerStyleItem?.Name}");
}
}
如您所见,默认搜索过滤器类型是搜索点符号。要搜索不同的符号类型,请在xaml中添加SearchFilterType属性-要么使用硬编码值,要么绑定到视图模型中的属性。
这是在xaml中硬编码的符号搜索器控件搜索颜色的相同示例。
xmlns:controls="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<StackPanel Orientation="Vertical">
<controls:SymbolSearcherControl x:Name="SymbolSearch"
SearchFilterType="Color"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"/>
<ListBox x:Name="SymbolPicker"
ItemsSource="{Binding Path=SearchResultStyleItems, ElementName=SymbolSearch, Mode=OneWay}"
SelectedItem="{Binding SelectedPickerStyleItem}"
DisplayMemberPath="Name"
HorizontalAlignment="Stretch"
VerticalAlignment="Top" MaxHeight="450"/>
StackPanel>
Symbol Searcher控件上可以选择指定的其他属性包括:
要将Symbol Searcher控件与Symbol PickerControl一起使用,请将以下内容添加到停靠窗格中。
xmlns:controls="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<StackPanel Grid.Row="1" Orientation="Vertical">
<controls:SymbolSearcherControl x:Name="SymbolSearch"
SearchFilterType="{Binding SearchFilterType}"
SearchPauseAutoSearch="{Binding SearchPauseSearching}" />
<controls:SymbolPickerControl x:Name="SymbolPicker"
PickerStyleItems="{Binding Path=SearchResultStyleItems, ElementName=SymbolSearch, Mode=OneWay}"
SelectedPickerStyleItem="{Binding SelectedPickerStyleItem, Mode=TwoWay}"
ViewingOption="{Binding PickerViewOption, Mode=TwoWay}"
GroupingOption="{Binding PickerGroupOption, Mode=TwoWay}"
HorizontalAlignment="Stretch"/>
StackPanel>
并将相应的属性添加到ViewModel代码隐藏类中:
using ArcGIS.Desktop.Mapping;
using ArcGIS.Desktop.Mapping.Controls;
protected CTOR_for_ViewModel()
{
SearchPauseSearching = false;
SearchFilterType = StyleItemType.PointSymbol;
}
private StyleItemType _searchFilterType;
public StyleItemType SearchFilterType
{
get => _searchFilterType;
set => SetProperty(ref _searchFilterType, value);
}
private bool _searchPauseSearching = true;
public bool SearchPauseSearching
{
private get => _searchPauseSearching;
set
{
SetProperty(ref _searchPauseSearching, value);
System.Diagnostics.Debug.WriteLine($@"==== SearchPauseSearching setter: {_searchPauseSearching}");
}
}
private StyleItem _selectedPickerStyleItem;
public StyleItem SelectedPickerStyleItem
{
get => _selectedPickerStyleItem;
set
{
SetProperty(ref _selectedPickerStyleItem, value);
MessageBox.Show($@"SelectedPickerStyleItem: {_selectedPickerStyleItem?.Name}");
}
}
private SymbolPickerViewOption _viewingOption = SymbolPickerViewOption.Icons;
public SymbolPickerViewOption PickerViewOption
{
get => _viewingOption;
set => SetProperty(ref _viewingOption, value);
}
private SymbolPickerGroupOption _groupingOption = SymbolPickerGroupOption.None;
public SymbolPickerGroupOption PickerGroupOption
{
get => _groupingOption;
set => SetProperty(ref _groupingOption, value);
}
使用Symbol Searcher和Symbol Picker控件的示例可以在使用SymbolSearcher控件中找到。
符号选取器控件用于从给定的样式项列表中“选取”特定的样式项。Symbol Picker控件可以与Symbol Searcher控件一起使用,为要从中选择的StyleItem列表添加素材,并且可以单独使用。
请参阅此处与SymbolSearcherControl结合使用的SymbolPickerControl:Symbol Searcher/Picker控件。
xmlns:controls="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<controls:SymbolPickerControl x:Name="SymbolPicker"
PickerStyleItems="{Binding Path=PickerStyleItems, Mode=OneWay}"
SelectedPickerStyleItem="{Binding SelectedPickerStyleItem}"
ViewingOption="{Binding ViewingOption}"
GroupingOption="{Binding GroupingOption}"
ShowOptionsDropDown="{Binding ShowOptionsDropDown, Mode=OneWay}"
/>
以及添加到ViewModel代码隐藏类中的相应属性:
protected override Task InitializeAsync()
{
return QueuedTask.Run(() =>
{
//Search for symbols in the selected style
StyleProjectItem si = Project.Current.GetItems().FirstOrDefault();
if (si != null)
{
var lstStyleItems = si.SearchSymbols(StyleItemType.PointSymbol, string.Empty).Select((s) => s as StyleItem);
RunOnUIThread(() =>
{
_pickerStyleItems = new ObservableCollection();
_pickerStyleItems.AddRange(lstStyleItems);
NotifyPropertyChanged(() => PickerStyleItems);
});
}
});
}
private ObservableCollection _pickerStyleItems;
public ObservableCollection PickerStyleItems
{
get => _pickerStyleItems;
set => SetProperty(ref _pickerStyleItems, value);
}
private StyleItem _selectedPickerStyleItem;
public StyleItem SelectedPickerStyleItem
{
get => _selectedPickerStyleItem;
set
{
SetProperty(ref _selectedPickerStyleItem, value);
MessageBox.Show($@"SelectedPickerStyleItem: {_selectedPickerStyleItem?.Name}");
}
}
private SymbolPickerViewOption _viewingOption;
public SymbolPickerViewOption ViewingOption
{
get => _viewingOption;
set => SetProperty(ref _viewingOption, value);
}
private SymbolPickerGroupOption _groupingOption;
public SymbolPickerGroupOption GroupingOption
{
get => _groupingOption;
set => SetProperty(ref _groupingOption, value);
}
private bool _showOptionsDropDown;
public bool ShowOptionsDropDown
{
get => _showOptionsDropDown;
set => SetProperty(ref _showOptionsDropDown, value);
}
#region Helpers
///
/// Utility function to enable an action to run on the UI thread (if not already)
///
/// the action to execute
///
internal static Task RunOnUIThread(Action action)
{
if (OnUIThread)
{
action();
return Task.FromResult(0);
}
else
return Task.Factory.StartNew(
action, System.Threading.CancellationToken.None, TaskCreationOptions.None, QueuedTask.UIScheduler);
}
///
/// Determines if the application is currently on the UI thread
///
private static bool OnUIThread
{
get
{
if (FrameworkApplication.TestMode)
return QueuedTask.OnWorker;
else
return System.Windows.Application.Current.Dispatcher.CheckAccess();
}
}
#endregion Helpers
使用Symbol Searcher和Symbol Picker控件的示例可以在使用SymbolSearcher控件中找到。
颜色选择器控件是一个UI组件,类似于属性选项卡下ArcGIS Pro Symbology停靠窗格上的核心颜色选择器控件。在外接程序中使用此控件,允许用户使用ArcGIS专业颜色选择器控件来选择颜色。使用CIMColor对象作为SelectedColor属性配置控件:
xmlns:mapping="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<mapping:ColorPickerControl x:Name="ColorPicker" SelectedColor="{Binding SelectedColor, Mode=TwoWay}" />
以及ViewModel代码隐藏类中相应的SelectedColor属性:
///
/// Color selection
///
private CIMColor _SelectedColor = CIMColor.CreateRGBColor(255, 0, 0);
public CIMColor SelectedColor
{
get => _SelectedColor;
set => SetProperty(ref _SelectedColor, value);
}
查询生成器控件提供了一个用于针对层或表生成查询表达式的UI。使用QueryBuilderControlProperties对象使用层或表和可选表达式配置查询生成器。
xmlns:mapping="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<mapping:QueryBuilderControl x:Name="QueryBuilderControl"
ConfigureControl="{Binding Path=ControlProperties}"/>
可以在QueryBuilderControl上找到使用QueryBuilder控件的示例。
Geocode Locator控件提供用于地理编码的UI。它的外观和行为与“定位”停靠窗格相同。它允许您添加、删除、重新排序、启用和禁用定位器。它还提供搜索和显示地理代码结果的功能。
xmlns:mapping="clr-namespace:ArcGIS.Desktop.Mapping.Controls;assembly=ArcGIS.Desktop.Mapping"
<mappingControls:LocatorControl x:Name="locator" />
可以在GeocodingTools上找到使用Geocode Locator控件的示例。
参考