Bir FeatureLayer'ın zaten var olup olmadığı nasıl doğrulanır?


9

Şu anda kullanıcı haritalarını (mxd) sistemimize yüklediğinde, onlar için birkaç özel featuerlayers oluşturduğumuz bir proje üzerinde çalışıyorum. Benim sorunum olsa da, ben zaten bu katmanları zaten oluşturduğumu kontrol etmek için hiçbir fikrim yok (kullanıcı mxd yükler, oluşturulan katmanlar kaydedin, kaydedin, mxd yeniden yükleyin, katmanlar zaten var olup olmadığını doğrulamak gerekir).

ArcEngine10'da bir FeatuerLayerClass için benzersiz bir kimlik var mı, FeatureLayerClass.FeatureClass içinde OIDName ve ObjectClassID var, ancak bunlar çalışmıyor gibi görünüyor (ObjectClassId atayamaz ve OIDName için UniqueId kullanmak ister)?

Katmanımı böyle bir özellik katmanı sınıfı iş nesnesi olarak oluşturdum.

Kod:

    /// <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;
        }
    }

Çalışma alanı oluşturma

    /// <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;

}

FeatureClass Oluşturma

        /// <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;

        }

Katman elde etmek için kod

            /// <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;
            }

Teşekkürler ve Saygılar, Kevin

Yanıtlar:


7

Özellik sınıfları ve nesne sınıfları, tek bir coğrafi veritabanında benzersiz olan kimliklerine sahiptir. Bu, çoğu zaman sizinkine benzer çoğu senaryoyu tatmin eder.

Bir katmanı özellik sınıfına göre benzersiz bir şekilde tanımlayamazsanız, katmanla rastgele veriler depolamak için katman uzantılarından yararlanabilirsiniz.

ILayerExtensions arabirimi aracılığıyla bir katmana katman uzantısı eklenebilir . Şimdi, katman uzantıları için ortak bir arabirim yoktur, ancak genellikle IPersistStream aracılığıyla bir miktar kalıcılık uygularlar . Katman uzantınız özel bir şey yapmaz, ancak eklenen katmanınızı benzersiz bir şekilde tanımlayacağınız bazı verileri depolar.

Yani göreviniz şöyle olacak:

  • Bayrağınızı (veya bir tür oluşturulan kimliği) depolayacak bir COM sınıfı oluşturun. Bu sınıf için IPersistStream öğesini uygulayın. EDIT: kendi sınıfını oluşturmak yerine bir PropertySet'i katman uzantısı nesnesi olarak kolayca kullanabilirsiniz .
  • Bir katman eklerken, haritadaki tüm katmanlar arasında geçiş yapın ve bunlardan herhangi birinin katman uzantısına sahip olup olmadığını, beklediğiniz depolanmış verilerle kontrol edin.
  • Bu durumda, katmanı zaten mevcut olduğu gibi eklemeyin.
  • Değilse, katmanı ekleyin ve katman uzantınızın bir örneğini ILayerExtensions üzerinden ekleyin.

Ben çok benzer bir sorun vardı ve katmanları uzantıları en uygun olduğu ortaya çıktı.

EDIT: aşağıda hızlı bir şekilde katman uzantısında (.NET 3.5 veya üstü gerekir) depolanan bir özellik kümesi içinde ayarlanmış özellikleri ile çalışmanıza olanak sağlar yardımcı statik sınıf için bazı kod gönderir. Uzantı nesnesine erişmeye ve katmana henüz atanmamışsa onu oluşturmaya özen gösterir. Bu şekilde kullanılır:

        // 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");

"SomeValue" yerine, muhtemelen bir tür katman tanımlayıcısı oluşturacak ve orada depolayacaksınız.

PropertySetLayerExtensionHelperSınıf için tam kaynak kodu :

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]);
        }
    }
}

Bazen, ILayerExtension'da özel bir anahtarla IPropertySet gibi bir şeyi depolamaktan kurtulabilirsiniz. Bu yaygın bir "hile" olduğundan, geliştiriciler bir IPropertySet'in varlığını kontrol etmeden önce kontrol etmelidir.
James Schek

@James: iyi bir ipucu, cevabı güncelleyeceğim.
Petr Krebs

+ 1 son kez Esri'nin katman uzantıları için yalnızca IPersistStream'i (IPersistVariant'ı değil) onurlandırdım. Neden olduğundan emin değilim. IPersistVariant desteğini bir geliştirici olarak sordum, ancak şimdiye kadar uygulandığından emin değilim. Her neyse, örnek kod için Richie Carmichael'ın IPersistStream gönderisini kullanmak isteyebilirsiniz .
Kirk Kuykendall

IPersistStream'i kullanma konusunda beni çıldırtan şey, Add-In'lerle çalışmadığı. ILayerExtensions öğesine eklediğiniz nesne COM CoCreatable olmalıdır.
James Schek

@Kirk: bu doğru, bu nedenle VB'de katman uzantısı kalıcılığını uygulayamadığımı hatırlıyorum. Düzeltme için teşekkürler.
Petr Krebs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.