Select to view content in your preferred language

Referencing a method from a different class within an Else statement and using 2 variables with the method

5492
12
Jump to solution
04-27-2015 09:05 AM
TiffanySelvidge1
Frequent Contributor

I am transferring a code from a VBA module to a C# arcmap add-in. I am using ArcMap 10.2 and Visual Studio 2010.

I cannot figure out how to translate what appears to be a method from a different class (module) within an ElseIf Not statement that places 2 variables from the current class within the method. The biggest problem for me in translating the code is that I can't really figure out with 100% certainty what the original code is saying with that ElseIf Not statement.

Any assistance will be appreciated.

This is the code snippet that I am referring to (ValidFacet is the method from a different module):

  ElseIf Not ValidFacet(txtFacetNumber.Text & cboFacetLetter.Text) Then
    MsgBox "The facet you entered does not exist." & vbCrLf & _
           "Please check and try again.", vbSystemModal

Here it is again within the original VBA code.

Private Sub cmdCreateFacet_Click()
  Dim strFacetNumber As String
  If txtFacetNumber.Text = "" Then
    MsgBox "You must inter a value for the facet.", vbCritical + vbSystemModal
    txtFacetNumber.SetFocus
    Exit Sub
  ElseIf cboFacetLetter.Text = "" And Not optFullFacet.Value Then
    MsgBox "You must inter a value for the facet letter.", vbCritical + vbSystemModal
    cboFacetLetter.SetFocus
    Exit Sub
  ElseIf Not ValidFacet(txtFacetNumber.Text & cboFacetLetter.Text) Then
    MsgBox "The facet you entered does not exist." & vbCrLf & _
           "Please check and try again.", vbSystemModal
    cboFacetLetter.Text = ""
    With txtFacetNumber
      .Text = ""
      .SetFocus
    End With
    Exit Sub
  End If
  
  strFacetNumber = txtFacetNumber.Text & cboFacetLetter.Text
  
  DrawMap strFacetNumber
  'MsgBox "Drawing"
  cmdExit_Click
  
End Sub

Here is my C# translation so far. I have created a different class (FacetClass) for the ValidFacet method. I reference the FacetClass namespace (SingleFacet1) within the 'using' section although both SingleFacetForm1 and FacetClass are from the same namespace.

 
public partial class SingleFacetForm1 : Form
    {

     private void searchBtn_Click(object sender, EventArgs e)
        {
            string facetNumberstr;
            
            if (facetNumbertxt.Text == "")
            {
                MessageBox.Show(new Form {TopMost = true }, "You must enter a value for the facet.");
                facetNumbertxt.Focus();
            }
                else if (qFacetCmb.Text == "" && !(wFacetrb.Checked))
                {
                    MessageBox.Show(new Form {TopMost = true }, "You must enter a value for the facet letter.");
                    qFacetCmb.Focus();
                }
                    else (! FacetClass.ValidFacet(facetNumbertxt.Text && qFacetCmb.Text))
                    {    
                        MessageBox.Show(new Form {TopMost = true }, "The facet you entered does not exist." + newLine + " " + "Please check and try again.");
                        qFacetCmb.Text = "";
                        facetNumbertxt.Text = "";
                        facetNumbertxt.Focus(); 
                    }
                            
            facetNumberstr = facetNumbertxt.Text + qFacetCmb.Text;
            
            facetNumberstr.DrawMap facetNumberstr;
            //facetNumberstr = new Draw(Map);
            //Draw(Map) (facetNumberstr);
            MessageBox.Show("Drawing");
            //cancelBtn_Click(); 
            cancelBtn_Click
        }

And just in case it helps, here is my C# code for ValidFacet:

 
public static void ValidFacet()
        {
            string newLine = System.Environment.NewLine;

            IMxDocument pMxDoc = ArcMap.Document;
            IMap pMap = pMxDoc.FocusMap;
            IFeatureLayer pFLayer;
            bool ValidFacet = true; 
            string facetStr = "";      
            int y;

            pFLayer = (IFeatureLayer)pMap.get_Layer(0); 

            for (y = 0; y <= pMap.LayerCount - 1; y++)
            {
                if (pMap.get_Layer(y).Name == "Facet")
                {
                    pFLayer = pMap.get_Layer(y) as IFeatureLayer;
                }

                else if (pFLayer as IFeatureLayer == null)
                {
                    MessageBox.Show("Failed to find the Facet Layer." + newLine + "Please check and try again");
                    ValidFacet = false;
                }                
            }

            //IFeatureLayer pFLayer;
            IGeoFeatureLayer pSearchLayer;
            IFeatureClass pSearchFC;
            IFeatureCursor pFCursor;
            IQueryFilter pQueryFilter;
            //pFLayer = pSearchLayer;
            pSearchLayer = (IGeoFeatureLayer)pFLayer;
            pSearchFC = pSearchLayer.DisplayFeatureClass;

            //Set queryfilter and search for pages to update
            pQueryFilter = new QueryFilter();
            String strSelField = "qfname";

            pQueryFilter.WhereClause = strSelField + " like '" + facetStr + "%'";
            pFCursor = pSearchFC.Search(pQueryFilter, false);

            if (pSearchFC.FeatureCount(pQueryFilter) < 1)
            {
                ValidFacet = false;
            }
        }
0 Kudos
1 Solution

Accepted Solutions
DanielRouleau
Occasional Contributor

I took a stab at taking your code and trying to mimic what I thought the Facet search code was looking to do, I've converted a LOT of VB code to C# over the years so hopefully this helps get pointed in the right direction. I tried to pepper in some comments to show what I think the original code was doing. Hope this helps!

            // Check if textbox was filled
            if (string.IsNullOrEmpty(facetNumbertxt.Text))
            {
                MessageBox.Show(new Form {TopMost = true}, "You must enter a value for the facet.");
                facetNumbertxt.Focus();
            }
            // Check if a combobox item was selected but the 'wFacetrb' checkbox was not checked
            else if (string.IsNullOrEmpty(qFacetCmb.Text) && !(wFacetrb.Checked))
            {
                MessageBox.Show(new Form {TopMost = true}, "You must enter a value for the facet letter.");
                qFacetCmb.Focus();
            }
            // We have fulfilled the textbox being filled, and combobox item chosen
            // perform search for Facet using the combination of textbox and combobox text as a single string
            // If not found, display messagebox.
            else if(!FacetClass.ValidFacet(facetNumbertxt.Text + qFacetCmb.Text))
            {
                MessageBox.Show(new Form {TopMost = true},
                    "The facet you entered does not exist." + Environment.NewLine + "Please check and try again.");
                qFacetCmb.Text = "";
                facetNumbertxt.Text = "";
                facetNumbertxt.Focus();
            }

And my take on the ValidFacet method:

        /// <summary>
        /// Searches the Facet feature class to find a feature matching 'facetstr'.
        /// Returns true if at least 1 feature is found, otherwise false.
        /// </summary>
        public static bool ValidFacet(string facetStr)
        {
            IMxDocument pMxDoc = ArcMap.Document;
            IMap pMap = pMxDoc.FocusMap;
            bool validFacet = true;

            IFeatureLayer pFLayer = null;

            // Loop through all layers until we find facet feature layer
            for (int y = 0; y <= pMap.LayerCount - 1; y++)
            {
                if (pMap.get_Layer(y).Name == "Facet")
                {
                    pFLayer = pMap.get_Layer(y) as IFeatureLayer;
                    break; // stop looking, we found it
                }
            }

            if (pFLayer == null)
            {
                MessageBox.Show("Failed to find the Facet Layer." + Environment.NewLine + "Please check and try again");
                validFacet = false;
            }
            else
            {
                IGeoFeatureLayer pSearchLayer = pFLayer as IGeoFeatureLayer;
                if (pSearchLayer != null)
                {
                    IFeatureClass pSearchFC = pSearchLayer.DisplayFeatureClass;

                    //Set queryfilter and search for pages to update
                    IQueryFilter pQueryFilter = new QueryFilter();
                    const string strSelField = "qfname";

                    pQueryFilter.WhereClause = strSelField + " like '" + facetStr + "%'";

                    if (pSearchFC.FeatureCount(pQueryFilter) < 1)
                    {
                        // We didn't find anything
                        validFacet = false;
                    }
                }
            }
            return validFacet;
        }

View solution in original post

12 Replies
TiffanySelvidge1
Frequent Contributor

I have encountered another instance where the same situation arises; ValidFacet is used in a different class and with a string parameter. I still cannot figure out exactly what the original vba code is trying to say or how to convert the vba to C#.

If Not ValidFacet(pTopFac) Then pTopFac = "END OF DATA" End If

So far I have this (which doesn't work):

if (FacetClass.ValidFacet() != pTopFac) { pTopFac = "END OF DATA"; }
0 Kudos
TiffanySelvidge1
Frequent Contributor

Since the statement seems to be checking to see if the variable's value exists in the ValidFacet,  I have also tried

if (!FacetClass.ValidFacet.Contains(pTopFac))

The statement does not work but perhaps it is closer to what is needed?

0 Kudos
TedKowal
Honored Contributor

Confusing....

Since VBA was used and VBA converts/casts anything to a variant data type that does not have a strict DIM statement could be your problem?

ValidFacet() ==> True, False, "Variant String"

If this is the case you may have to accommodate this additional situation..... VBA will try an convert any failed datatype to variant.  Some other programmer, being on the lazy side or employing a quick fix used this leniency of VBA to create additional functionality without having to rip apart code to create additional logic.

Just a thought that may trigger some additional ideas for you?

TiffanySelvidge1
Frequent Contributor

Ted,

Thank you for your help. I was not aware of VBA's automatic conversion to variant. It is something I am now trying to make sure I consider as the problem when encountering other errors.

0 Kudos
TedKowal
Honored Contributor

I cannot tell you how many times that variant has bit me....

Sneaky example:   Dim i,j,k,l as integer

You would expect i,j,k,l to be integers but no  ...  i is an integer, j,k,l will be variants.  (This one is a killer!)

TiffanySelvidge1
Frequent Contributor

I am glad you mentioned that example. I never would have thought that to be the case.

0 Kudos
DanielRouleau
Occasional Contributor

I took a stab at taking your code and trying to mimic what I thought the Facet search code was looking to do, I've converted a LOT of VB code to C# over the years so hopefully this helps get pointed in the right direction. I tried to pepper in some comments to show what I think the original code was doing. Hope this helps!

            // Check if textbox was filled
            if (string.IsNullOrEmpty(facetNumbertxt.Text))
            {
                MessageBox.Show(new Form {TopMost = true}, "You must enter a value for the facet.");
                facetNumbertxt.Focus();
            }
            // Check if a combobox item was selected but the 'wFacetrb' checkbox was not checked
            else if (string.IsNullOrEmpty(qFacetCmb.Text) && !(wFacetrb.Checked))
            {
                MessageBox.Show(new Form {TopMost = true}, "You must enter a value for the facet letter.");
                qFacetCmb.Focus();
            }
            // We have fulfilled the textbox being filled, and combobox item chosen
            // perform search for Facet using the combination of textbox and combobox text as a single string
            // If not found, display messagebox.
            else if(!FacetClass.ValidFacet(facetNumbertxt.Text + qFacetCmb.Text))
            {
                MessageBox.Show(new Form {TopMost = true},
                    "The facet you entered does not exist." + Environment.NewLine + "Please check and try again.");
                qFacetCmb.Text = "";
                facetNumbertxt.Text = "";
                facetNumbertxt.Focus();
            }

And my take on the ValidFacet method:

        /// <summary>
        /// Searches the Facet feature class to find a feature matching 'facetstr'.
        /// Returns true if at least 1 feature is found, otherwise false.
        /// </summary>
        public static bool ValidFacet(string facetStr)
        {
            IMxDocument pMxDoc = ArcMap.Document;
            IMap pMap = pMxDoc.FocusMap;
            bool validFacet = true;

            IFeatureLayer pFLayer = null;

            // Loop through all layers until we find facet feature layer
            for (int y = 0; y <= pMap.LayerCount - 1; y++)
            {
                if (pMap.get_Layer(y).Name == "Facet")
                {
                    pFLayer = pMap.get_Layer(y) as IFeatureLayer;
                    break; // stop looking, we found it
                }
            }

            if (pFLayer == null)
            {
                MessageBox.Show("Failed to find the Facet Layer." + Environment.NewLine + "Please check and try again");
                validFacet = false;
            }
            else
            {
                IGeoFeatureLayer pSearchLayer = pFLayer as IGeoFeatureLayer;
                if (pSearchLayer != null)
                {
                    IFeatureClass pSearchFC = pSearchLayer.DisplayFeatureClass;

                    //Set queryfilter and search for pages to update
                    IQueryFilter pQueryFilter = new QueryFilter();
                    const string strSelField = "qfname";

                    pQueryFilter.WhereClause = strSelField + " like '" + facetStr + "%'";

                    if (pSearchFC.FeatureCount(pQueryFilter) < 1)
                    {
                        // We didn't find anything
                        validFacet = false;
                    }
                }
            }
            return validFacet;
        }
TiffanySelvidge1
Frequent Contributor

Daniel,

Thanks for your help, the code appears to work! I have other code I am working on that are tied-in to that code so I can't currently test it but all the errors are gone and other areas that were also using a ValidFacet reference are no longer showing errors.

I am interested in the logic and reasoning behind the changes you made. If you don't mind, I know (and appreciate) that you have already spend quite a bit of time translating the code, I have a few questions about some of your modifications.

First, what made you decide to change from 'void' to 'bool'? I have other class programs that use boolean in the code but I have as 'void' in the return type.

Second, I noticed you are not using the IFeatureCursor. Why is it no longer needed; ie. what code modifications made IFeatureCursor obsolete?

Lastly, why were you able to define pFlayer as null instead of using    pFLayer = (IFeatureLayer)pMap.get_Layer(0); . Is it because you upgraded the else if to an if and included in the logic statement else for pSearchLayer = pFlayer and set it to for a non-blank pSearchLayer?

0 Kudos
DanielRouleau
Occasional Contributor

1. Regarding using bool instead of void, I see that you are trying to use it in an if statement, so the return type will have to be bool in C# to be contained within the if block. In VBA, I'd presume it looked something like

Public Function ValidFacet(ByVal sFacetNumber As String, ByVal sFacetLetter as String) As Boolean

which should imply the same thing, the function itself returns a Boolean value.

2. When looking at what the ValidFacet code was doing, it looked like it was only checking the count, which is accomplished with just the call

pSearchFC.FeatureCount(pQueryFilter)

If you wanted to use the actual features associated with that search, you'd use the results from the feature cursor itself, but since we were just checking count, we can omit the feature cursor call, and just get the count.

3. My thought process around the changes here were to try to optimize the bit of code to exit out as soon as it finds the layer. I initalize the layer to null, so that if we go through all of the layers and don't find it, we can check the layer for null and exit. Another option would look like this

            for (int y = 0; y <= pMap.LayerCount - 1; y++)
            {
                pFLayer = pMap.get_Layer(y) as IFeatureLayer;
                if (pFLayer != null && pFLayer.Name == "Facet")
                {
                    break; // stop looking, we found it
                }
            }

In either case, I am using whether or not pFLayer is null to decide whether to continue looking for the feature.

I'm hoping that helps give some background as to why I made the choices I did, always happy to share any knowledge I may have.