ArcObjects Library Reference  

FieldPropertyDescriptor

Bind a geodatabase table to a .NET control

[C#]

FieldPropertyDescriptor.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;

namespace ArcDataBinding
{
  /// <summary>
  /// This class provides a PropertyDescriptor for a single field of an IRow
  /// </summary>
  /// <remarks>
  /// This class can be used by an ITypedList implementation to provide a property
  /// description for a single field in an ITable.
  /// </remarks>
  internal class FieldPropertyDescriptor: PropertyDescriptor
  {
    #region Private Members
    /// <summary>
    /// Store the index of the IField that this property descriptor describes
    /// </summary>
    private int wrappedFieldIndex;
    
    /// <summary>
    /// Store the .NET type of the value stored in the IField this property
    /// represents
    /// </summary>
    private Type netType;

    /// <summary>
    /// This is used to store the actual .NET type of a field that uses a CV
    /// domain. It retains the type allowing as to restore it when the UseCVDomain
    /// property is false;
    /// </summary>
    private Type actualType;
    
    /// <summary>
    /// Store the esri type of the value stored in the IField this property
    /// represents
    /// </summary>
    private esriFieldType esriType;
    
    /// <summary>
    /// Indicates whether this field is editable or not.
    /// </summary>
    /// <remarks>
    /// This will determined by looking at the Editable property of the IField
    /// and the type of the field. We currently don't support the editing of
    /// blob or geometry fields.
    /// </remarks>
    bool isEditable = true;

    /// <summary>
    /// Used to start and stop editing when adding/updating/deleting rows
    /// </summary>
    private IWorkspaceEdit wkspcEdit;

    /// <summary>
    /// The coded value domain for the field this instance represents, if any
    /// </summary>
    private ICodedValueDomain cvDomain;

    /// <summary>
    /// This will be true if we are currently using the string values for the
    /// coded value domain and false if we are using the numeric values.
    /// </summary>
    private bool useCVDomain;

    /// <summary>
    /// This type converter is used when the field this instance represents has
    /// a coded value domain and we are displaying the actual domain values
    /// </summary>
    private TypeConverter actualValueConverter;

    /// <summary>
    /// This type converter is used when the field this instance represents has
    /// a coded value domain and we are displaying the names of the domain values
    /// </summary>
    private TypeConverter cvDomainValDescriptionConverter;
    #endregion Private Members

    #region Construction/Destruction
    /// <summary>
    /// Initializes a new instance of the <see cref="FieldPropertyDescriptor"/> class.
    /// </summary>
    /// <param name="wrappedTable">The wrapped table.</param>
    /// <param name="fieldName">Name of the field within wrappedTable.</param>
    /// <param name="fieldIndex">Index of the field within wrappedTable.</param>
    public FieldPropertyDescriptor(ITable wrappedTable, string fieldName, int fieldIndex)
      : base(fieldName, null)
    {
      wrappedFieldIndex = fieldIndex;

      // Get the field this property will represent. We will use it to
      // get the field type and determine whether it can be edited or not. In
      // this case, editable means the field's editable property is true and it
      // is not a blob, geometry or raster field.
      IField wrappedField = wrappedTable.Fields.get_Field(fieldIndex);
      esriType = wrappedField.Type;
      isEditable = wrappedField.Editable && 
        (esriType != esriFieldType.esriFieldTypeBlob) &&
        (esriType != esriFieldType.esriFieldTypeRaster) &&
        (esriType != esriFieldType.esriFieldTypeGeometry);
      netType = actualType = EsriFieldTypeToSystemType(wrappedField);
      wkspcEdit = ((IDataset)wrappedTable).Workspace as IWorkspaceEdit;
    } 
    #endregion Construction/Destruction

    /// <summary>
    /// Gets a value indicating whether the field represented by this property 
    /// has a CV domain.
    /// </summary>
    /// <value>
    /// 	<c>true</c> if this instance has a CV domain; otherwise, <c>false</c>.
    /// </value>
    public bool HasCVDomain
    {
      get
      {
        return null != cvDomain;
      }
    }

    /// <summary>
    /// Sets a value indicating whether [use CV domain].
    /// </summary>
    /// <value><c>true</c> if [use CV domain]; otherwise, <c>false</c>.</value>
    public bool UseCVDomain
    {
      set
      {
        useCVDomain = value;
        if (value)
        {
          // We want the property type for this field to be string
          netType = typeof(string);
        }
        else
        {
          // Restore the original type
          netType = actualType;
        }
      }
    }

    #region Public Overrides
    /// <summary>
    /// Gets the type converter for this property.
    /// </summary>
    /// <remarks>
    /// We need to override this property as the base implementation sets the
    /// converter once and reuses it as required. We can't do this if the field
    /// this instance represents has a coded value domain and we change from
    /// using the value to using the name or vice versa. The reason for this is
    /// that if we are displaying the domain name, we need a string converter and
    /// if we are displaying the domain value, we will need one of the numeric
    /// converters.
    /// </remarks>
    /// <returns>A <see cref="T:System.ComponentModel.TypeConverter"></see> 
    /// that is used to convert the <see cref="T:System.Type"></see> of this 
    /// property.</returns>
    /// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, 
    /// mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
    /// version="1" Flags="UnmanagedCode"/></PermissionSet>
    public override TypeConverter Converter
    {
      get
      {
        TypeConverter retVal = null;

        if (null != cvDomain)
        {
          if (useCVDomain)
          {
            if (null == cvDomainValDescriptionConverter)
            {
              // We want a string converter
              cvDomainValDescriptionConverter = TypeDescriptor.GetConverter(typeof(string));
            }

            retVal = cvDomainValDescriptionConverter;
          }
          else
          {
            if (null == actualValueConverter)
            {
              // We want a converter for the type of this field's actual value
              actualValueConverter = TypeDescriptor.GetConverter(actualType);
            }

            retVal = actualValueConverter;
          }
        }
        else
        {
          // This field doesn't have a coded value domain, the base implementation
          // works fine.
          retVal = base.Converter;
        }

        return retVal;
      }
    }

    /// <summary>
    /// Returns whether resetting an object changes its value.
    /// </summary>
    /// <param name="component">The component to test for reset capability.
    /// This will be an IRow</param>
    /// <returns>
    /// true if resetting the component changes its value; otherwise, false.
    /// </returns>
    public override bool CanResetValue(object component)
    {
      return false;
    }

    /// <summary>
    /// Gets the type of the component this property is bound to.
    /// </summary>
    /// <value></value>
    /// <returns>A <see cref="T:System.Type"></see> that represents the type of 
    /// component this property is bound to. When the 
    /// <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"></see> 
    /// or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"></see> 
    /// methods are invoked, the object specified might be an instance of this type.</returns>
    public override Type ComponentType
    {
      get { return typeof(IRow); }
    }

    /// <summary>
    /// Gets the current value of the property on a component.
    /// </summary>
    /// <param name="component">The component (an IRow) with the property for 
    /// which to retrieve the value.</param>
    /// <remarks>
    /// This will return the field value for all fields apart from geometry, raster and Blobs.
    /// These fields will return the string equivalent of the geometry type.
    /// </remarks>
    /// <returns>
    /// The value of a property for a given component. This will be the value of
    /// the field this class instance represents in the IRow passed in the component
    /// parameter.
    /// </returns>
    public override object GetValue(object component)
    {
      object retVal = null;

      IRow givenRow = (IRow)component;
      try
      {
        // Get value
        object value = givenRow.get_Value(wrappedFieldIndex);

        if ((null != cvDomain) && useCVDomain)
        {
          value = cvDomain.get_Name(Convert.ToInt32(value));
        }

        switch (esriType)
        {
            case esriFieldType.esriFieldTypeBlob:
                retVal = "Blob";
                break;
            
            case esriFieldType.esriFieldTypeGeometry:
                retVal = GetGeometryTypeAsString(value);
                break;
            
            case esriFieldType.esriFieldTypeRaster:
                retVal = "Raster";
                break;
            
            default:
                retVal = value;
                break;
        }
      }
      catch (Exception e)
      {
        System.Diagnostics.Debug.WriteLine(e.Message);
      }

      return retVal;
    }

    /// <summary>
    /// Gets a value indicating whether this property is read-only or not.
    /// </summary>
    /// <value></value>
    /// <returns>true if the property is read-only; otherwise, false.</returns>
    public override bool IsReadOnly
    {
      get { return !isEditable; }
    }

    /// <summary>
    /// Gets the type of the property.
    /// </summary>
    /// <value></value>
    /// <returns>A <see cref="T:System.Type"></see> that represents the type 
    /// of the property.</returns>
    public override Type PropertyType
    {
      get { return netType; }
    }

    /// <summary>
    /// Resets the value for this property of the component to the default value.
    /// </summary>
    /// <param name="component">The component (an IRow) with the property value 
    /// that is to be reset to the default value.</param>
    public override void ResetValue(object component)
    {

    }

    /// <summary>
    /// Sets the value of the component to a different value.
    /// </summary>
    /// <remarks>
    /// If the field this instance represents does not have a coded value domain,
    /// this method simply sets the given value and stores the row within an edit
    /// operation. If the field does have a coded value domain, the method first
    /// needs to check that the given value is valid. If we are displaying the 
    /// coded values, the value passed to this method will be a string and we will
    /// need to see if it is one of the names in the cv domain. If we are not
    /// displaying the coded values, we will still need to check that the given
    /// value is within the domain. If the value is not within the domain, an
    /// error will be displayed and the method will return.
    /// Note that the string comparison is case sensitive.
    /// </remarks>
    /// <param name="component">The component (an IRow) with the property value 
    /// that is to be set.</param>
    /// <param name="value">The new value.</param>
    public override void SetValue(object component, object value)
    {
      IRow givenRow = (IRow)component;

      if (null != cvDomain)
      {
        // This field has a coded value domain
        if (!useCVDomain)
        {
          // Check value is valid member of the domain
          if (!((IDomain)cvDomain).MemberOf(value))
          {
            System.Windows.Forms.MessageBox.Show(string.Format(
              "Value {0} is not valid for coded value domain {1}", value.ToString(), ((IDomain)cvDomain).Name));
            return;
          }
        }
        else
        {
          // We need to convert the string value to one of the cv domain values
          // Loop through all the values until we, hopefully, find a match
          bool foundMatch = false;
          for (int valueCount = 0; valueCount < cvDomain.CodeCount; valueCount++)
          {
            if (value.ToString() == cvDomain.get_Name(valueCount))
            {
              foundMatch = true;
              value = valueCount;
              break;
            }
          }

          // Did we find a match?
          if (!foundMatch)
          {
            System.Windows.Forms.MessageBox.Show(string.Format(
              "Value {0} is not valid for coded value domain {1}", value.ToString(), ((IDomain)cvDomain).Name));
            return;
          }
        }
      }
      givenRow.set_Value(wrappedFieldIndex, value);

      // Start editing if we aren't already editing
      bool weStartedEditing = false;
      if (!wkspcEdit.IsBeingEdited())
      {
        wkspcEdit.StartEditing(false);
        weStartedEditing = true;
      }

      // Store change in an edit operation
      wkspcEdit.StartEditOperation();
      givenRow.Store();
      wkspcEdit.StopEditOperation();

      // Stop editing if we started here
      if (weStartedEditing)
      {
        wkspcEdit.StopEditing(true);
      }

    }

    /// <summary>
    /// When overridden in a derived class, determines a value indicating whether 
    /// the value of this property needs to be persisted.
    /// </summary>
    /// <param name="component">The component (an IRow) with the property to be examined for 
    /// persistence.</param>
    /// <returns>
    /// true if the property should be persisted; otherwise, false.
    /// </returns>
    public override bool ShouldSerializeValue(object component)
    {
      return false;
    } 
    #endregion Public Overrides

    #region Private Methods
    /// <summary>
    /// Converts the specified ESRI field type to a .NET type.
    /// </summary>
    /// <param name="esriType">The ESRI field type to be converted.</param>
    /// <returns>The appropriate .NET type.</returns>
    private Type EsriFieldTypeToSystemType(IField field)
    {
      esriFieldType esriType = field.Type;

      // Does this field have a domain?
      cvDomain = field.Domain as ICodedValueDomain;
      if ((null != cvDomain) && useCVDomain)
      {
        return typeof(string);
      }

      try
      {
        switch (esriType)
        {
          case esriFieldType.esriFieldTypeBlob:
            //beyond scope of sample to deal with blob fields
            return typeof(string);
          case esriFieldType.esriFieldTypeDate:
            return typeof(DateTime);
          case esriFieldType.esriFieldTypeDouble:
            return typeof(double);
          case esriFieldType.esriFieldTypeGeometry:
            return typeof(string);
          case esriFieldType.esriFieldTypeGlobalID:
            return typeof(string);
          case esriFieldType.esriFieldTypeGUID:
            return typeof(Guid);
          case esriFieldType.esriFieldTypeInteger:
            return typeof(Int32);
          case esriFieldType.esriFieldTypeOID:
            return typeof(Int32);
          case esriFieldType.esriFieldTypeRaster:
            //beyond scope of sample to correctly display rasters
            return typeof(string);
          case esriFieldType.esriFieldTypeSingle:
            return typeof(Single);
          case esriFieldType.esriFieldTypeSmallInteger:
            return typeof(Int16);
          case esriFieldType.esriFieldTypeString:
            return typeof(string);
          default:
            return typeof(string);
        }
      }
      catch (Exception ex)
      {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        return typeof(string);
      }
    }

    /// <summary>
    /// Gets the geometry type as string.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns>The string equivalent of the geometry type</returns>
    private string GetGeometryTypeAsString(object value)
    {
      string retVal = "";
      IGeometry geometry = value as IGeometry;
      if (geometry != null)
      {
        retVal = geometry.GeometryType.ToString();
      }
      return retVal;
    }
    #endregion Private Methods
  }
}

[Visual Basic .NET]

FieldPropertyDescriptor.vb

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.ComponentModel
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.GeomeTry

Namespace ArcDataBinding
    '<summary>
    'This class provides a PropertyDescriptor for a single field of an IRow
    '</summary>
    '<remarks>
    'This class can be used by an ITypedList implementation to provide a property
    'description for a single field in an ITable.
    '</remarks>
    Friend Class FieldPropertyDescriptor
        Inherits PropertyDescriptor
#Region "Private Members"
        '<summary>
        'Store the index of the IField that this property descriptor describes
        '</summary>
        Private wrappedFieldIndex As Integer

        '<summary>
        'Store the .NET type of the value stored in the IField this property
        'represents
        '</summary>
        Private netType As Type

        '<summary>
        'This is used to store the actual .NET type of a field that uses a CV
        'domain. It retains the type allowing as to restore it when the UseCVDomain
        'property is false;
        '</summary>
        Private actualType As Type

        '<summary>
        'Store the esri type of the value stored in the IField this property
        'represents
        '</summary>
        Private esriType As esriFieldType

        '<summary>
        'Indicates whether this field is editable or not.
        '</summary>
        '<remarks>
        'This will determined by looking at the Editable property of the IField
        'and the type of the field. We currently don't support the editing of
        'blob or geometry fields.
        '</remarks>
        Dim isEditable As Boolean = True

        '<summary>
        'Used to start and stop editing when adding/updating/deleting rows
        '</summary>
        Private wkspcEdit As IWorkspaceEdit

        '<summary>
        'The coded value domain for the field this instance represents, if any
        '</summary>
        Private cvDomain As ICodedValueDomain

        '<summary>
        'This will be true if we are currently using the string values for the
        'coded value domain and false if we are using the numeric values.
        '</summary>
        Private useCVDomain As Boolean

        '<summary>
        'This type converter is used when the field this instance represents has
        'a coded value domain and we are displaying the actual domain values
        '</summary>
        Private actualValueConverter As TypeConverter

        '<summary>
        'This type converter is used when the field this instance represents has
        'a coded value domain and we are displaying the names of the domain values
        '</summary>
        Private cvDomainValDescriptionConverter As TypeConverter
#End Region

#Region "Construction/Destruction"
        '<summary>
        'Initializes a new instance of the <see cref="FieldPropertyDescriptor"/> class.
        '</summary>
        '<param name="wrappedTable">The wrapped table.</param>
        '<param name="fieldName">Name of the field within wrappedTable.</param>
        '<param name="fieldIndex">Index of the field within wrappedTable.</param>
        Public Sub New(ByVal wrappedTable As ITable, ByVal fieldName As String, ByVal fieldIndex As Integer)
            : MyBase.New(fieldName, Nothing)

            wrappedFieldIndex = fieldIndex

            'Get the field this property will represent. We will use it to
            'get the field type and determine whether it can be edited or not. In
            'this case, editable means the field's editable property is true and it
            'is not a blob, geometry or raster field.
            Dim wrappedField As IField = DirectCast(wrappedTable.Fields.Field(fieldIndex), IField)
            esriType = wrappedField.Type
            isEditable = wrappedField.Editable AndAlso _
              (esriType <> esriFieldType.esriFieldTypeBlob) AndAlso _
              (esriType <> esriFieldType.esriFieldTypeRaster) AndAlso _
              (esriType <> esriFieldType.esriFieldTypeGeometry)
            actualType = EsriFieldTypeToSystemType(wrappedField)
            netType = actualType
            wkspcEdit = DirectCast((DirectCast(wrappedTable, IDataset)).Workspace, IWorkspaceEdit)
        End Sub

#End Region

        '<summary>
        'Gets a value indicating whether the field represented by this property 
        'has a CV domain.
        '</summary>
        '<value>
        '	<c>true</c> if this instance has a CV domain; otherwise, <c>false</c>.
        '</value>
        Public ReadOnly Property HasCVDomain() As Boolean
            Get
                HasCVDomain = Not (Nothing Is cvDomain)
            End Get
        End Property

        '<summary>
        'Sets a value indicating whether [use CV domain].
        '</summary>
        '<value><c>true</c> if [use CV domain]; otherwise, <c>false</c>.</value>
        Public WriteOnly Property SetUseCVDomain() As Boolean
            Set(ByVal Value As Boolean)
                useCVDomain = Value
                If (Value) Then
                    ' We want the property type for this field to be string
                    netType = GetType(String)
                Else
                    ' Restore the original type
                    netType = actualType
                End If
            End Set
        End Property

#Region "Public Overrides"
        '<summary>
        'Gets the type converter for this property.
        '</summary>
        '<remarks>
        'We need to override this property as the base implementation sets the
        'converter once and reuses it as required. We can't do this if the field
        'this instance represents has a coded value domain and we change from
        'using the value to using the name or vice versa. The reason for this is
        'that if we are displaying the domain name, we need a string converter and
        'if we are displaying the domain value, we will need one of the numeric
        'converters.
        '</remarks>
        '<returns>A <see cref="T:System.ComponentModel.TypeConverter"></see> 
        'that is used to convert the <see cref="T:System.Type"></see> of this 
        'property.</returns>
        '<PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, 
        'mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
        'version="1" Flags="UnmanagedCode"/></PermissionSet>
        Public Overrides ReadOnly Property Converter() As TypeConverter
            Get
                Dim retVal As TypeConverter = Nothing

                If Not (Nothing Is cvDomain) Then

                    If (useCVDomain) Then
                        If (Nothing Is cvDomainValDescriptionConverter) Then
                            ' We want a string converter
                            cvDomainValDescriptionConverter = TypeDescriptor.GetConverter(GetType(String))
                        End If

                        retVal = cvDomainValDescriptionConverter
                    Else
                        If (Nothing Is actualValueConverter) Then
                            ' We want a converter for the type of this field's actual value
                            actualValueConverter = TypeDescriptor.GetConverter(actualType)
                        End If

                        retVal = actualValueConverter
                    End If

                Else

                    ' This field doesn't have a coded value domain, the base implementation
                    ' works fine.
                    retVal = MyBase.Converter
                End If

                Converter = retVal
            End Get
        End Property

        '<summary>
        'Returns whether resetting an object changes its value.
        '</summary>
        '<param name="component">The component to test for reset capability.
        'This will be an IRow</param>
        '<returns>
        'true if resetting the component changes its value; otherwise, false.
        '</returns>
        Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
            CanResetValue = False
        End Function

        '<summary>
        'Gets the type of the component this property is bound to.
        '</summary>
        '<value></value>
        '<returns>A <see cref="T:System.Type"></see> that represents the type of 
        'component this property is bound to. When the 
        '<see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"></see> 
        'or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"></see> 
        'methods are invoked, the object specified might be an instance of this type.</returns>
        Public Overrides ReadOnly Property ComponentType() As Type
            Get
                ComponentType = GetType(IRow)
            End Get
        End Property

        '<summary>
        'Gets the current value of the property on a component.
        '</summary>
        '<param name="component">The component (an IRow) with the property for 
        'which to retrieve the value.</param>
        '<remarks>
        'This will return the field value for all fields apart from geometry, raster and Blobs.
        'These fields will return the string equivalent of the geometry type.
        '</remarks>
        '<returns>
        'The value of a property for a given component. This will be the value of
        'the field this class instance represents in the IRow passed in the component
        'parameter.
        '</returns>
        Public Overrides Function GetValue(ByVal component As Object) As Object
            Dim retVal As Object = Nothing

            Dim givenRow As IRow = DirectCast(component, IRow)
            Try
                ' Get value
                Dim value As Object = givenRow.Value(wrappedFieldIndex)

                If (Not (Nothing Is cvDomain) AndAlso useCVDomain) Then
                    value = cvDomain.Name(Convert.ToInt32(value))
                End If


                Select Case esriType
                    Case esriFieldType.esriFieldTypeBlob
                        retVal = "Blob"
                        Exit Select
                    Case esriFieldType.esriFieldTypeGeometry

                        retVal = GetGeomeTryTypeAsString(value)
                        Exit Select
                    Case esriFieldType.esriFieldTypeRaster

                        retVal = "Raster"
                        Exit Select
                    Case Else

                        retVal = value
                        Exit Select
                End Select


            Catch e As Exception
                System.Diagnostics.Debug.WriteLine(e.Message)
            End Try

            GetValue = retVal
        End Function

        '<summary>
        'Gets a value indicating whether this property is read-only or not.
        '</summary>
        '<value></value>
        '<returns>true if the property is read-only; otherwise, false.</returns>
        Public Overrides ReadOnly Property IsReadOnly() As Boolean
            Get
                IsReadOnly = Not isEditable
            End Get
        End Property

        '<summary>
        'Gets the type of the property.
        '</summary>
        '<value></value>
        '<returns>A <see cref="T:System.Type"></see> that represents the type 
        'of the property.</returns>
        Public Overrides ReadOnly Property PropertyType() As Type
            Get
                PropertyType = netType
            End Get
        End Property

        '<summary>
        'Resets the value for this property of the component to the default value.
        '</summary>
        '<param name="component">The component (an IRow) with the property value 
        'that is to be reset to the default value.</param>
        Public Overrides Sub ResetValue(ByVal component As Object)
        End Sub

        '<summary>
        'Sets the value of the component to a different value.
        '</summary>
        '<remarks>
        'If the field this instance represents does not have a coded value domain,
        'this method simply sets the given value and stores the row within an edit
        'operation. If the field does have a coded value domain, the method first
        'needs to check that the given value is valid. If we are displaying the 
        'coded values, the value passed to this method will be a string and we will
        'need to see if it is one of the names in the cv domain. If we are not
        'displaying the coded values, we will still need to check that the given
        'value is within the domain. If the value is not within the domain, an
        'error will be displayed and the method will return.
        'Note that the string comparison is case sensitive.
        '</remarks>
        '<param name="component">The component (an IRow) with the property value 
        'that is to be set.</param>
        '<param name="value">The new value.</param>
        Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
            Dim givenRow As IRow = DirectCast(component, IRow)

            If Not (Nothing Is cvDomain) Then
                ' This field has a coded value domain
                If (Not useCVDomain) Then
                    ' Check value is valid member of the domain
                    If (Not (DirectCast(cvDomain, IDomain)).MemberOf(value)) Then _
                      System.Windows.Forms.MessageBox.Show(String.Format( _
                        "Value {0} is not valid for coded value domain {1}", value.ToString(), (DirectCast(cvDomain, IDomain)).Name))
                    Return
                Else
                    ' We need to convert the string value to one of the cv domain values
                    ' Loop through all the values until we, hopefully, find a match
                    Dim foundMatch As Boolean = False
                    Dim valueCount As Integer
                    For valueCount = 0 To cvDomain.CodeCount - 1 Step valueCount + 1
                        If (value.ToString() = cvDomain.Name(valueCount)) Then
                            foundMatch = True
                            value = valueCount
                        End If
                        Exit For
                    Next


                    ' Did we find a match?
                    If (Not foundMatch) Then
                        System.Windows.Forms.MessageBox.Show(String.Format( _
                        "Value {0} is not valid for coded value domain {1}", value.ToString(), (DirectCast(cvDomain, IDomain)).Name))
                        Return
                    End If
                End If
            End If

            givenRow.Value(wrappedFieldIndex) = value

            ' Start editing if we aren't already editing
            Dim weStartedEditing As Boolean = False
            If (Not wkspcEdit.IsBeingEdited()) Then
                wkspcEdit.StartEditing(False)
                weStartedEditing = True
                ' Store change in an edit operation
                wkspcEdit.StartEditOperation()
                givenRow.Store()
                wkspcEdit.StopEditOperation()
            End If
            ' Stop editing if we started here
            If (weStartedEditing) Then
                wkspcEdit.StopEditing(True)
            End If

        End Sub

        '<summary>
        'When overridden in a derived class, determines a value indicating whether 
        'the value of this property needs to be persisted.
        '</summary>
        '<param name="component">The component (an IRow) with the property to be examined for 
        'persistence.</param>
        '<returns>
        'true if the property should be persisted; otherwise, false.
        '</returns>
        Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
            ShouldSerializeValue = False
        End Function

#End Region

#Region "Private Methods"
        '<summary>
        'Converts the specified ESRI field type to a .NET type.
        '</summary>
        '<param name="esriType">The ESRI field type to be converted.</param>
        '<returns>The appropriate .NET type.</returns>
        Function EsriFieldTypeToSystemType(ByVal field As IField) As Type
            Dim esriType As esriFieldType = field.Type

            ' Does this field have a domain?
            cvDomain = TryCast(field.Domain, ICodedValueDomain)
            If (Not (Nothing Is cvDomain) AndAlso useCVDomain) Then
                EsriFieldTypeToSystemType = GetType(String)
                Exit Function
            End If

            Try
                Select Case esriType
                    Case esriFieldType.esriFieldTypeBlob
                        'beyond scope of sample to deal with blob fields
                        EsriFieldTypeToSystemType = GetType(String)
                    Case esriFieldType.esriFieldTypeDate
                        EsriFieldTypeToSystemType = GetType(DateTime)
                    Case esriFieldType.esriFieldTypeDouble
                        EsriFieldTypeToSystemType = GetType(Double)
                    Case esriFieldType.esriFieldTypeGeometry
                        EsriFieldTypeToSystemType = GetType(String)
                    Case esriFieldType.esriFieldTypeGlobalID
                        EsriFieldTypeToSystemType = GetType(String)
                    Case esriFieldType.esriFieldTypeGUID
                        EsriFieldTypeToSystemType = GetType(Guid)
                    Case esriFieldType.esriFieldTypeInteger
                        EsriFieldTypeToSystemType = GetType(Int32)
                    Case esriFieldType.esriFieldTypeOID
                        EsriFieldTypeToSystemType = GetType(Int32)
                    Case esriFieldType.esriFieldTypeRaster
                        'beyond scope of sample to correctly display rasters
                        EsriFieldTypeToSystemType = GetType(String)
                    Case esriFieldType.esriFieldTypeSingle
                        EsriFieldTypeToSystemType = GetType(Single)
                    Case esriFieldType.esriFieldTypeSmallInteger
                        EsriFieldTypeToSystemType = GetType(Int16)
                    Case esriFieldType.esriFieldTypeString
                        EsriFieldTypeToSystemType = GetType(String)
                    Case Else
                        EsriFieldTypeToSystemType = GetType(String)
                End Select
            Catch ex As Exception
                System.Diagnostics.Debug.WriteLine(ex.Message)
                EsriFieldTypeToSystemType = GetType(String)
            End Try
        End Function

        '<summary>
        'Gets the geometry type as string.
        '</summary>
        '<param name="value">The value.</param>
        '<returns>The string equivalent of the geometry type</returns>
        Private Function GetGeomeTryTypeAsString(ByVal value As Object) As String
            Dim retVal As String = ""
            Dim geomeTry As IGeometry = TryCast(value, IGeometry)
            If Not (geomeTry Is Nothing) Then
                retVal = geomeTry.GeometryType.ToString()
            End If
            GetGeomeTryTypeAsString = retVal
        End Function
#End Region
    End Class
End Namespace