Làm cách nào để xác minh nếu FeatureLayer đã tồn tại?


9

Tôi hiện đang làm việc trong một dự án khi người dùng tải lên bản đồ của họ (mxd) vào hệ thống của chúng tôi, chúng tôi tạo ra một số featuerlayers tùy chỉnh cho họ. Vấn đề của tôi là mặc dù, tôi không biết làm thế nào để kiểm tra xem tôi đã ALREADY đã tạo các lớp đó chưa (giả sử người dùng tải lên mxd, các lớp được tạo, lưu, tải lại mxd, nên xác minh xem các lớp đã tồn tại chưa).

Có Id duy nhất cho FeatuerLayerClass trong ArcEngine10, có OIDName và ObjectClassID trong FeatureLayerClass.FeatureClass, nhưng những thứ đó dường như không hoạt động (không thể gán ObjectClassId và muốn sử dụng UniqueId cho OIDName)?

Tôi đã tạo lớp của mình là đối tượng kinh doanh featurelayerclass như thế này.

Mã số:

    /// <summary>
    ///     Unique Route LayerId
    /// </summary>
    public static Guid RouteFeatureLayerId
    {
        get { return Guid.Parse("ba25a332-0e48-4ce5-a4c5-38dc36c0700c"); }
    }

    /// <summary>
    ///     Feature class that stores info on the routes
    /// </summary>
    public FeatureLayerClass RouteFeatureLayer
    {
        get
        {
            if (_routeFeatureClass == null)
            {
                IPropertySet property = new PropertySetClass();
                property.SetProperty("Id", RouteFeatureLayerId);

                _routeFeatureClass = new FeatureLayerClass();
                _routeFeatureClass.FeatureClass = CreateFeatureClass(Workspace, null, ShapeType.Polylines.ToString(), CreateFields(ShapeType.Polylines, FeatureLayerType.Routes), null, null, "");
                _routeFeatureClass.Name = "Routes";
                _routeFeatureClass.Visible = true;
                _routeFeatureClass.Cached = true;
                _routeFeatureClass.AddExtension(property);
                CustomLayers.Add(_routeFeatureClass); 

            }

            return _routeFeatureClass;
        }
        set
        {
            _routeFeatureClass = value;
        }
    }

Tạo không gian làm việc

    /// <summary>
    ///     Create a workspace for the shapefile or geodatabase
    /// </summary>
private IWorkspace CreateWorkspace(string workspaceType, string workspaceDirectory)
{
    Type factoryType = null;
    IWorkspaceFactory workspaceFactory = null;

    switch (workspaceType)
    {
        case "Shapefile":
            // Instantiate a Shapefile workspace factory
            factoryType = Type.GetTypeFromProgID("esriDataSourcesFile.ShapefileWorkspaceFactory");
            break;
        case "PersonalGeodatabase":
            // Instantiate an Access workspace factory
            factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
            break;
        case "FileGeodatabase":
            // Instantiate a file geodatabase workspace factory
            factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            break;
    }

    workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);

    //Create a directory hierarchy to seperate out datasets created for Points, Polylines, and Polygons
    Directory.CreateDirectory(workspaceDirectory);

    IWorkspaceName workspaceName = workspaceFactory.Create(workspaceDirectory + "\\", workspaceType, null, 0);
    IName Name = (IName)workspaceName;
    IWorkspace workspace = (IWorkspace)(Name.Open());
    return workspace;

}

Tạo FeatureClass

        /// <summary>
        ///     Helper to create a Feature Class.
        /// </summary>
        private IFeatureClass CreateFeatureClass(IWorkspace workspace, IFeatureDataset featureDataset, string featureClassName, IFields fields, ESRI.ArcGIS.esriSystem.UID CLSID, ESRI.ArcGIS.esriSystem.UID CLSEXT, string configKeyword)
        {
            IFeatureClass featureClass = null;
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace; // Explicit Cast
            string shapeFieldName = String.Empty;

            try
            {
                if (featureClassName == "")
                {
                    return null; // name was not passed in
                }
                //else if (((IWorkspace2)workspace).get_NameExists(esriDatasetType.esriDTFeatureClass, featureClassName))
                //{
                //    featureClass = featureWorkspace.OpenFeatureClass(featureClassName); // feature class with that name already exists
                //    return featureClass;
                //}

                // assign the class id value if not assigned
                if (CLSID == null)
                {
                    CLSID = new ESRI.ArcGIS.esriSystem.UIDClass();
                    CLSID.Value = "esriGeoDatabase.Feature";
                }

                // locate the shape field
                for (Int32 j = 0; j < fields.FieldCount; j++)
                {
                    if (fields.get_Field(j).Type == esriFieldType.esriFieldTypeGeometry)
                    {
                        shapeFieldName = fields.get_Field(j).Name;
                    }
                }

                // finally create and return the feature class
                if (featureDataset == null)
                {
                    // if no feature dataset passed in, create at the workspace level
                    featureClass = featureWorkspace.CreateFeatureClass(featureClassName, fields, CLSID, CLSEXT, esriFeatureType.esriFTSimple, shapeFieldName, configKeyword);
                }
                else
                {
                    featureClass = featureDataset.CreateFeatureClass(featureClassName, fields, CLSID, CLSEXT, esriFeatureType.esriFTSimple, shapeFieldName, configKeyword);
                }
            }
            catch (Exception ex)
            {
                Debug.Assert(false, ex.ToString());
                Logger.Log.Debug(ex);
            }
            return featureClass;

        }

Mã để có được lớp

            /// <summary>
            ///     Finds the layer
            /// </summary>
            /// <returns>the subcatchment layer</returns>
            private IGeoFeatureLayer GetLayer(FeatureLayerClass featureLayer)
            {
                IGeoFeatureLayer layer = null;
                ILayerExtensions layerExtension;

                for (int x = 0; x < MapControl.LayerCount; x++)
                {
                    layerExtension = ((ILayerExtensions)MapControl.get_Layer(x));

                    if (featureLayer.ExtensionCount > 0 && layerExtension.ExtensionCount > 0 &&
                        layerExtension.get_Extension(0) is PropertySetClass &&
                        featureLayer.get_Extension(0) is PropertySetClass &&
                        ((PropertySetClass)layerExtension.get_Extension(0)).GetProperty("Id") == ((PropertySetClass)featureLayer.get_Extension(0)).GetProperty("Id"))
                    {
                        layer = MapControl.get_Layer(x) as IGeoFeatureLayer;
                        break;
                    }
                }

                return layer;
            }

Cảm ơn và trân trọng, Kevin

Câu trả lời:


7

Các lớp đối tượng và các lớp đối tượng có id của chúng, là duy nhất trong một cơ sở dữ liệu địa lý duy nhất. Điều này rất thường đáp ứng hầu hết các kịch bản tương tự như của bạn.

Nếu bạn không thể xác định duy nhất một lớp dựa trên lớp tính năng của nó, bạn có thể tận dụng các phần mở rộng lớp để lưu trữ dữ liệu tùy ý với lớp đó.

Một phần mở rộng lớp có thể được thêm vào một lớp thông qua giao diện ILayerExtensions . Bây giờ, không có giao diện chung cho các phần mở rộng lớp, nhưng chúng thường thực hiện một số kiên trì thông qua IPersistStream . Phần mở rộng lớp của bạn sẽ không làm gì đặc biệt nhưng lưu trữ một số dữ liệu mà theo đó bạn sẽ xác định duy nhất lớp đã thêm của mình.

Vì vậy, nhiệm vụ của bạn sẽ như sau:

  • Tạo một lớp COM sẽ lưu trữ cờ của bạn (hoặc một số loại Id được tạo). Triển khai IPersistStream cho lớp này. EDIT: bạn có thể dễ dàng sử dụng Thuộc tính làm đối tượng mở rộng lớp, thay vì tạo lớp của riêng bạn.
  • Khi bạn đang thêm một lớp, hãy lặp qua tất cả các lớp trong bản đồ và kiểm tra xem bất kỳ lớp nào trong số chúng có phần mở rộng lớp của bạn được chỉ định hay không, với dữ liệu được lưu trữ mà bạn mong đợi.
  • Nếu đó là trường hợp, không thêm lớp như nó đã có.
  • Nếu không, hãy thêm lớp và thêm một thể hiện của phần mở rộng lớp của bạn vào nó thông qua ILayerExtensions.

Tôi đã có một vấn đề rất giống nhau và các phần mở rộng lớp hóa ra là phù hợp nhất.

EDIT: bên dưới tôi đăng một số mã cho lớp tĩnh của trình trợ giúp cho phép bạn nhanh chóng làm việc với các thuộc tính được đặt bên trong một tập thuộc tính được lưu trữ trong phần mở rộng lớp (yêu cầu .NET 3.5 trở lên). Nó đảm nhiệm việc truy cập đối tượng mở rộng và tạo nó nếu chưa được gán cho lớp. Nó được sử dụng như thế này:

        // 1) is a particular property ("MY.KEY") set on a layer?
        var isPropertySet = PropertySetLayerExtensionHelper.ExtensionPropertySetContainsKey(layer, "MY.KEY");

        // 2) set a property with a value on the layer:
        PropertySetLayerExtensionHelper.ExtensionPropertySetSetValueForKey(layer, "MY.KEY", "SomeValue");

        // 3) retrieve a value for the given key stored at some point before:
        var value = PropertySetLayerExtensionHelper.ExtensionPropertySetGetValueForKey(layer, "MY.KEY");

Thay vì "Một số giá trị", bạn có thể sẽ tạo và lưu trữ một số loại định danh lớp trong đó.

Đây là mã nguồn đầy đủ cho PropertySetLayerExtensionHelperlớp:

public static class PropertySetLayerExtensionHelper
{
    /// <summary>
    /// Returns whether the property set stored in the layer extensions contains a value for the given key.
    /// </summary>
    /// <param name="layer">The layer.</param>
    /// <param name="key">The key.</param>
    /// <returns>Whether the property set stored in the layer extensions contains a value for the given key.</returns>
    public static bool ExtensionPropertySetContainsKey(ILayer layer, string key)
    {
        if (layer == null) throw new ArgumentNullException("layer");
        if (key == null) throw new ArgumentNullException("key");

        var propertySet = GetPropertySetInLayerExtension(layer);
        return propertySet != null
            && propertySet.AsEnumerable().Any(pair => pair.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
    }

    /// <summary>
    /// Returns the value for the given key from the property set stored in the layer extension or <b>null</b>
    /// if no such key is present.
    /// </summary>
    /// <param name="layer">The layer.</param>
    /// <param name="key">The key.</param>
    /// <returns>The value for the given key from the property set stored in the layer extension or <b>null</b>
    /// if no such key is present.</returns>
    public static object ExtensionPropertySetGetValueForKey(ILayer layer, string key)
    {
        if (layer == null) throw new ArgumentNullException("layer");
        if (key == null) throw new ArgumentNullException("key");

        var propertySet = GetPropertySetInLayerExtension(layer);
        if (propertySet == null) return null;

        return propertySet.AsEnumerable()
            .Where(p => p.Key.Equals(key, StringComparison.OrdinalIgnoreCase))
            .Select(p => p.Value)
            .FirstOrDefault();
    }

    /// <summary>
    /// Sets the value for the given key in the property set stored in a layer extension. If there is
    /// no property set among the layer's extensions, it is created and assigned to the layer.
    /// </summary>
    /// <param name="layer">The layer.</param>
    /// <param name="key">The key.</param>
    /// <param name="value">The value for the given key.</param>
    public static void ExtensionPropertySetSetValueForKey(ILayer layer, string key, object value)
    {
        if (layer == null) throw new ArgumentNullException("layer");
        if (key == null) throw new ArgumentNullException("key");

        var propertySet = GetOrCreatePropertySetInLayerExtension(layer);
        if (propertySet == null)
        {
            throw new InvalidOperationException("The given layer does not support layer extensions.");
        }

        propertySet.SetProperty(key, value);
    }

    /// <summary>
    /// Returns a property set from a layer extension.
    /// </summary>
    /// <param name="layer">The layer.</param>
    /// <returns>A property set from a layer extension.</returns>
    public static IPropertySet GetPropertySetInLayerExtension(ILayer layer)
    {
        if (layer == null) throw new ArgumentNullException("layer");

        var layerExtensions = layer as ILayerExtensions;
        if (layerExtensions == null)
        {
            return null;
        }

        var propertySetExtension = layerExtensions.AsEnumerable().OfType<IPropertySet>().FirstOrDefault();
        return propertySetExtension;
    }

    /// <summary>
    /// Returns a property set from a layer extension. If not set on the layer,
    /// the property set is created and assigned to it.
    /// </summary>
    /// <param name="layer">The layer.</param>
    /// <returns>A property set from a layer extension.</returns>
    public static IPropertySet GetOrCreatePropertySetInLayerExtension(ILayer layer)
    {
        if (layer == null) throw new ArgumentNullException("layer");

        var propertySet = GetPropertySetInLayerExtension(layer);
        if (propertySet != null)
        {
            return propertySet;
        }

        var layerExtensions = layer as ILayerExtensions;
        if (layerExtensions == null)
        {
            return null;
        }

        propertySet = new PropertySetClass();
        layerExtensions.AddExtension(propertySet);
        return propertySet;
    }

    private static IEnumerable<object> AsEnumerable(this ILayerExtensions layerExtensions)
    {
        if (layerExtensions == null) throw new ArgumentNullException("layerExtensions");

        for (var i = 0; i < layerExtensions.ExtensionCount; i++)
        {
            yield return layerExtensions.get_Extension(i);
        }
    }

    private static IEnumerable<KeyValuePair<string, object>> AsEnumerable(this IPropertySet propertySet)
    {
        if (propertySet == null) throw new ArgumentNullException("propertySet");
        if (propertySet.Count == 0) yield break;

        object names;
        object values;

        propertySet.GetAllProperties(out names, out values);

        var nameArray = (string[])names;
        var valueArray = (object[])values;

        for (var i = 0; i < nameArray.Length; i++)
        {
            yield return new KeyValuePair<string, object>(nameArray[i], valueArray[i]);
        }
    }
}

Đôi khi, bạn có thể thoát khỏi việc chỉ lưu trữ thứ gì đó như IPropertyset với một khóa đặc biệt trong ILayerExtension. Vì đây là một "mẹo" phổ biến, các nhà phát triển nên kiểm tra sự tồn tại của IPropertyset trước khi thêm.
James Schek

@James: mẹo hay, tôi sẽ cập nhật câu trả lời.
Petr Krebs

+1 lần trước tôi đã kiểm tra Esri chỉ vinh danh IPersistStream - không phải IPersistVariant - cho các tiện ích mở rộng lớp. Tôi cung không chăc tại sao. Tôi đã yêu cầu hỗ trợ IPersistVariant như một sự nâng cao, nhưng không chắc nó đã được thực hiện. Dù sao, bạn có thể muốn sử dụng bài đăng IPersistStream của Richie Carmichael cho mã mẫu.
Kirk Kuykendall

Điều khiến tôi phát điên khi sử dụng IPersistStream là nó không hoạt động với Add-In. Đối tượng bạn thêm vào ILayerExtensions phải là COM CoCreatable.
James Schek

@Kirk: đúng vậy, tôi nhớ là không thể thực hiện tính bền vững của phần mở rộng lớp trong VB do đó. Cảm ơn vì sự đúng đắn của bạn.
Petr Krebs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.