Click here to Skip to main content
15,896,557 members
Articles / Programming Languages / C#

AppXmlViewer: Between Doxygen and raw XML

Rate me:
Please Sign up or sign in to vote.
3.46/5 (4 votes)
5 Apr 2007CPOL6 min read 34.8K   420   19  
Utility for viewing an application's document XML in a DataGridView.
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using System.Xml;

using VVX;

namespace VVX_AppXmlViewer
{
    /// <summary>
    /// Main form of this application
    /// </summary>
    public partial class Form_VVX_AppXmlView : Form
    {
        private string msAppName = "VVX AppXmlViewer ";
        private string msExeFolder = "";
        private string msInfoFile = "";
        private string msFileXML = "";

        private string msClassToList = "";   //empty means ALL Classes


        /// <summary>
        /// The only constructor for this form
        /// </summary>
        public Form_VVX_AppXmlView()
        {
            InitializeComponent();
            msExeFolder = VVX.FileDialog.DoGetAppPath("");
            DoUpdateCaption();
        }

        #region Misc Form Helper
        //************************************************************
        /// <summary>
        /// Refreshes the window's Caption/Title bar
        /// </summary>
        private void DoUpdateCaption()
        {
            this.Text = this.msAppName;

            if (this.msFileXML.Length == 0)
            {
                this.Text += "<no XML file opened>";
            }
            else
            {
                FileInfo fi = new FileInfo(this.msFileXML);
                this.Text += @"...\" + fi.Name;
            }
        }

        private void OnFormShown(object sender, EventArgs e)
        {
            this.DoNavigateToInfoPage();
            VVX.About.Show();   //OK to comment this out.
            this.DoGridStatus(this.ctlTableDGV);

        }

        /// <summary>
        /// Moves up the directory tree and locates the info HTML file
        /// </summary>
        private void DoNavigateToInfoPage()
        {
            if (this.msInfoFile.Length == 0 && VVX.File.Exists(this.msInfoFile) == false)
            {
                msInfoFile = "vvxAppXmlViewer.html";

                string sPath = msInfoFile;
                for (int i = 0; i < 6; i++)
                {
                    if (VVX.File.Exists(sPath))
                    {
                        FileInfo fi = new FileInfo(sPath);
                        this.ctlInfoBrowser.Navigate(fi.FullName);
                        this.msInfoFile = fi.FullName;
                        break;
                    }
                    sPath = @"..\" + sPath;
                }
            }
            else
            {
                this.ctlInfoBrowser.Navigate(this.msInfoFile);
            }
        }

        #endregion //Misc Form Helper

        #region Help Menu Helpers
        private void ctlHelpAboutMNU_Click(object sender, EventArgs e)
        {
            VVX.About.Show();
        }

        private void ctlHelpGetPDFArticleMNU_Click(object sender, EventArgs e)
        {
            string sURL = "http://www.codeproject.com/useritems/iTextSharpPdfTables.asp";
            this.ctlInfoBrowser.Navigate(sURL);
            this.ctl_MainTabControl.SelectedIndex = 0;
        }
        #endregion //Help Menu Helpers

        #region File Helpers
        private void ctlFileExitMNU_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ctlFileOpenMNU_Click(object sender, EventArgs e)
        {
            DoFileOpen(true);
        }

        private bool DoFileOpen(bool bSwitchToTableTab)
        {
            string sFileXML 
                = VVX.FileDialog.GetFilenameToOpen(VVX.FileDialog.FileType.XML
                                                 , msExeFolder);

            if (VVX.File.Exists(sFileXML))
            {
                msFileXML = sFileXML;
                msClassToList = "";
                this.DoUpdateCaption();
                this.ctlInfoBrowser.Navigate(msFileXML);
                this.ctl_MainTabControl.SelectedIndex = 0;
                this.DoGridEmpty(this.ctlTableDGV);

                if (bSwitchToTableTab) 
                    this.DoViewTableTabPageInit();

                return true;
            }

            return false;
        }
        #endregion //File Helpers


        /// <summary>
        /// Main method that is used to retrieve the data from the Application's Doc XML
        /// and then display its contents in a DataGridView
        /// </summary>
        private void DoViewTableTabPageInit()
        {
            if (VVX.File.Exists(this.msFileXML) == false)
                this.DoFileOpen(true);

            if (VVX.File.Exists(this.msFileXML) == true)
            {
                if (this.ctlTableDGV.ColumnCount == 0)
                {
                    //--- create an instance of AppXmlDoc which will parse the XML file
                    VVX.AppXmlDoc appXml = new AppXmlDoc(this.msFileXML);

                    //--- set the options of the subsets you want to see
                    appXml.IncludeF = this.ctlViewIncludeFieldsMNU.Checked;
                    appXml.IncludeP = this.ctlViewIncludePropertiesMNU.Checked;
                    appXml.IncludeT = this.ctlViewIncludeTypesMNU.Checked;
                    appXml.IncludeM = this.ctlViewIncludeMethodsMNU.Checked;
                    appXml.IncludeMp = this.ctlViewIncludeMethodParamsMNU.Checked;
                    appXml.IncludeMr = this.ctlViewIncludeMethodReturnMNU.Checked;
                    appXml.IncludeE = this.ctlViewIncludeEsMNU.Checked;

                    //--- apply a "class" filter (default is to list info from ALL classes)
                    int nSelIndex = ctlClassCBX.SelectedIndex;

                    //--- now let AppXmlDoc instance parse the file 
                    //    (using the class filter, if any, to)
                    appXml.DoExtractMemberData(msClassToList);

                    //--- now load the DataGridView
                    int nCount = appXml.Members.Count;

                    //---'decorate' the DataGridView
                    this.DoGridCustomization(this.ctlTableDGV);

                    //---set columns headers
                    this.DoGridPopulate(this.ctlTableDGV, appXml);

                    //---load the class list ComboBox
                    DoLoadClasses(appXml.Classes, msClassToList);

                    this.ctlViewRefreshBTN.Enabled = false;

                }

                //--- switch to the tab with the data
                this.ctl_MainTabControl.SelectedIndex = 1;
            }
            else
            {
                MsgBox.Info("Nothing to display!");
            }
        }

        private void DoLoadClasses(ArrayList arraylist, string sSel)
        {
            this.ctlClassCBX.Items.Clear();
            this.ctlClassCBX.Items.Add("ALL Classes");
            arraylist.Sort();
            int nSel = 0;
            for (int i = 0; i < arraylist.Count; i++)
            {
                string sVal = arraylist[i].ToString();
                this.ctlClassCBX.Items.Add(sVal);
                if (sVal == sSel)
                    nSel = i+1;
            }


            this.ctlClassCBX.SelectedIndex = nSel;


        }

        #region Grid Helper Methods
        private void DoGridEmpty(DataGridView dgv)
        {
            dgv.ColumnCount = 0;
            dgv.RowCount = 0;
            DoGridStatus(dgv);
        }

        private void DoGridStatus(DataGridView dgv)
        {
            int rows = dgv.RowCount;
            if (rows == 0)
            {
                this.ctlDgvStatusLBL.Text = "You need to open a file.";
            }
            else
            {
                this.ctlDgvStatusLBL.Text = rows.ToString() + " members listed";
            }
        }

        /// <summary>
        /// Normally invoked once at startup
        /// </summary>
        /// <param name="dgv">The DataGridView to be customized</param>

        private void DoGridCustomization(DataGridView dgv)
        {
            //--- configure the GRID
            dgv.Name = "Table";
            //dgv.Location = new Point(8, 8);
            //dgv.Size = new Size(500, 250);
            //dgv.Dock = DockStyle.Fill;

            //--- if you don't want an empty "new row" to be displayed at the bottom
            //    set AllowUserToAddRows = false;
            dgv.AllowUserToAddRows = false;

            //--- to speed up the "painting" of the grid
            //    set AutoSizeColumnsMode and AutoSizeRowsMode to "None." 
            //    Ref:http://www.developerdotstar.com/community/node/706
            dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
            //dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders;

            //--- configure the ROW and COLUMN HEADERS
            dgv.RowHeadersVisible = true;
            dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            //dgv.ColumnHeadersDefaultCellStyle.BackColor = Color.Navy;
            //dgv.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
            //dgv.ColumnHeadersDefaultCellStyle.Font = new Font(dgv.Font, FontStyle.Bold);
            //--- to speed up the "painting" of the grid
            //    Ref:http://www.developerdotstar.com/community/node/706
            //    set EnableVisualStyles=false
            //dgv.EnableHeadersVisualStyles= false;
            //dgv.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;

            //--- to speed up the "painting" of the grid
            //    set CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.None
            //    Ref:https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=117093
            //    and http://blogs.msdn.com/jfoscoding/archive/2005/11/16/493727.aspx
            //    and http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49#Data%20Access

            //--- configure CELLS
            //dgv.GridColor = Color.Black;
            //dgv.CellBorderStyle = DataGridViewCellBorderStyle.Single;
            //dgv.CellBorderStyle = DataGridViewCellBorderStyle.None;

            //--- configure other things

            //--- Add default Excel-like column headers
            dgv.Columns.Clear();
            int start = (int)'A';
            for (int i = 0; i < 26; i++)
            {
                string colName = ((char)(i + start)).ToString();
                int index = dgv.Columns.Add(colName, colName);
                dgv.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
                dgv.Columns[i].Width = 75;
            }

            //--- Add add empty rows
            //this.mbSetRowHeaderLabel = false;  //Used by OnRowsAdded(...)
            dgv.RowHeadersWidth = 49;
            for (int i = 0; i < 50; i++)
            {
                dgv.Rows.Add(); //generates an event --> OnRowsAdded(...)
            }

            //--- specify how the user SELECTs one or more cells
            dgv.MultiSelect = false;
            dgv.SelectionMode = DataGridViewSelectionMode.CellSelect;
            //dgv.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect;
            //dgv.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
            //dgv.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
            //dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

            //--- define an event handler that allows you to format each cell
            dgv.CellFormatting +=
                new DataGridViewCellFormattingEventHandler(OnCellFormatting);
        }

        private void OnCellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
        }

        /// <summary>
        /// Invoked after an AppXml file is opened by user to display its contents
        /// in a DataGridView
        /// </summary>
        /// <param name="dgv">DataGridView instance in which to display the data</param>
        /// <param name="appXmlDoc">instance of AppXmlDoc</param>
        private void DoGridPopulate(DataGridView dgv, VVX.AppXmlDoc appXmlDoc)
        {
            this.Cursor = Cursors.WaitCursor;

            int numMembers = appXmlDoc.Members.Count;
            bool bShowMembersNumber = true;

            try
            {
                if (numMembers > 0)
                {
                    dgv.Columns.Clear();
                    int nExtraCol = (bShowMembersNumber?1:0);
                    dgv.ColumnCount = appXmlDoc.ColumnCount + nExtraCol;
                    int n = 0;
                    //int iXX = (int) Math.Floor((1+Math.Log10((double) numMembers)));
                    int iKluge = (int)(Math.Pow(10.0, Math.Floor((1 + Math.Log10((double)numMembers)))));
                    if (bShowMembersNumber)
                    {
                        dgv.Columns[n++].Name = "#";
                    }
                    for (n = 0; n < appXmlDoc.ColumnCount; n++)
                    {
                        dgv.Columns[n + nExtraCol].Name = appXmlDoc.Title[n];
                    }

                    for (int i = 0; i < numMembers; i++)
                    {
                        VVX.AppXmlMember mem = (VVX.AppXmlMember) appXmlDoc.Members[i];
                        string[] rowCells = new string[nExtraCol + appXmlDoc.ColumnCount];
                        n = -1;
                        if (bShowMembersNumber)
                        {
                            string sNum = (1+ i + iKluge).ToString();
                            sNum = sNum.Remove(0, 1);
                            ++n; rowCells[n] = sNum;
                        }

                        ++n; rowCells[n] = mem.Qualifier;
                        ++n; rowCells[n] = mem.Type;
                        ++n; rowCells[n] = mem.Namespace;
                        ++n; rowCells[n] = mem.Class;
                        ++n; rowCells[n] = mem.Name;
                        ++n; rowCells[n] = mem.Summary;
                        dgv.Rows.Add(rowCells);
                    }

                    //MsgBox.Warning("The XmlStore file is 'ReadOnly'. You will not be able to save any changes");

                    dgv.AutoResizeColumns();
                }
            }
            catch (Exception ex)
            {
                string sMsg = ex.ToString();
                Debug.WriteLine(sMsg);
                MsgBox.Error(sMsg);
            }

            DoGridStatus(dgv);

            this.Cursor = Cursors.Default;
        }
        #endregion //Grid Helper Methods

        #region Print Helper Methods
        private void ctlFilePrintPreviewMNU_Click(object sender, EventArgs e)
        {
            bool bPreview = true;
            bool bSetup = true;
            bool bPrint = true;
            this.DoPrint(bSetup, bPreview, bPrint);
        }

        private void ctlFilePrintMNU_Click(object sender, EventArgs e)
        {
            bool bPreview = false;
            bool bSetup = true;
            bool bPrint = true;
            this.DoPrint(bSetup, bPreview, bPrint);
        }

        private void DoPrint(bool bSetup, bool bPreview, bool bPrint)
        {
            if (this.ctlTableDGV.ColumnCount > 0)
            {
                VVX.Print dgvPrint = new Print(this.ctlTableDGV, bSetup, bPreview, bPrint);

                if (dgvPrint != null)
                {
                    string sStamp = DateTime.Now.ToShortDateString()
                                  + ":"
                                  + DateTime.Now.ToShortTimeString()
                                  ;
                    string sSpace = "........";
                    string sTitle = ""//this.msAppName + "Report on "
                                  + VVX.File.DoExtractFilename(this.msFileXML)
                                  + sSpace + "(as of " + sStamp + ")"
                                  ;
                    dgvPrint.PrintTitle = sTitle;

                    bool bSelectColumns = true;
                    if (bSelectColumns)
                        dgvPrint.PrintHowDGV = Print.HowToPrintDGV.SelectedColumns;
                    else
                        dgvPrint.PrintHowDGV = Print.HowToPrintDGV.Everything;

                    dgvPrint.DoPrintDGV();
                }
            }
            else
            {
                MsgBox.Info("You need to open a file first!");
            }
        }
        #endregion //Print Helper Methods

        #region View Menu Helper Methods

        private void ctlViewXmlMNU_Click(object sender, EventArgs e)
        {
            if (VVX.File.Exists(this.msFileXML))
            {
                this.ctlInfoBrowser.Navigate(msFileXML);
            }
            else
            {
                this.DoViewTableTabPageInit();
            }
            this.ctl_MainTabControl.SelectedIndex = 0;

        }

        private void ctlViewPdfMNU_Click(object sender, EventArgs e)
        {
            string sMsg = "";
            sMsg = "This version will export an XmlStore file which, in turn, "
                  + "can be converted into a PDF using another utility.\n"
                  + "\n"
                  + "See 'Creating PDF Tables using C# (.NET 2.0) and iTextSharp'\n"
                  + "at http://www.codeproject.com/useritems/iTextSharpPdfTables.asp"
                  + "\n"
                  ;

            MsgBox.Info(sMsg);
        }

        private void ctlViewTableMNU_Click(object sender, EventArgs e)
        {
            this.DoViewTableTabPageInit();
        }

        private void OnViewRefresh(object sender, EventArgs e)
        {
            DoGridEmpty(this.ctlTableDGV);
            DoViewTableTabPageInit();
            this.ctlViewRefreshBTN.Enabled = false ;

        }

        private void ctlViewIncludeTypesMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludeTypesMNU.Checked = !ctlViewIncludeTypesMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void ctlViewIncludeMethodsMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludeMethodsMNU.Checked = !ctlViewIncludeMethodsMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void ctlViewIncludePropertiesMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludePropertiesMNU.Checked = !ctlViewIncludePropertiesMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void ctlViewIncludeEnumsMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludeFieldsMNU.Checked = !ctlViewIncludeFieldsMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void ctlViewIncludeMethodParamsMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludeMethodParamsMNU.Checked = !ctlViewIncludeMethodParamsMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void ctlViewIncludeMethodReturnMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludeMethodReturnMNU.Checked = !ctlViewIncludeMethodReturnMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void ctlViewIncludeEsMNU_Click(object sender, EventArgs e)
        {
            ctlViewIncludeEsMNU.Checked = !ctlViewIncludeEsMNU.Checked;
            this.ctlViewRefreshBTN.Enabled = true;
        }

        private void OnClassChanged(object sender, EventArgs e)
        {
            if (ctlClassCBX.Items.Count > 0)
            {
                int n = ctlClassCBX.SelectedIndex;
                if (n < 1)
                    this.msClassToList = "";
                else
                {
                    this.msClassToList = ctlClassCBX.SelectedItem.ToString();
                }
                this.ctlViewRefreshBTN.Enabled = true;
            }
        }
        #endregion //View Menu Helper Methods

        #region File Export Helpers
        private void ctlFileExportXmlStoreMNU_Click(object sender, EventArgs e)
        {
            this.DoExportXmlStore(this.ctlTableDGV);
        }

        private bool DoExportXmlStore(DataGridView dgv)
        {
            bool bRet = false;
            string sEOL = Environment.NewLine;
            if (msFileXML.Length == 0)
            {
                MsgBox.Info("Please open an application xml first");
                return bRet;
            }
            string sFile = msFileXML.Substring(0, msFileXML.LastIndexOf("."))
                         + ".XmlStore.xml";
            sFile = VVX.FileDialog.GetFilenameToSave(VVX.FileDialog.FileType.XML, sFile);

            if (sFile.Length > 0 && dgv.ColumnCount > 0)
            {
                //--- make sure you are not replacing the app.xml file
                if (sFile.ToLower() != this.msFileXML.ToLower())
                {
                    string sXML = "";
                    sXML += "<?xml version='1.0' encoding='utf-8'?>" + sEOL;
                    sXML += "<xmlStore version='1.0'>" + sEOL;
                    sXML += "  <schema datanodename='member'>" + sEOL;
                    sXML += "    <field width='10' alignH='L' name='ID' title='#' />" + sEOL;
                    sXML += "    <field width='20' alignH='L' name='Qualifier' title='Qualifier' />" + sEOL;
                    sXML += "    <field width='20' alignH='L' name='Type' title='Type' />" + sEOL;
                    sXML += "    <field width='20' alignH='L' name='Namespace' title='Namespace' />" + sEOL;
                    sXML += "    <field width='20' alignH='L' name='Class' title='Class' />" + sEOL;
                    sXML += "    <field width='30' alignH='L' name='Name' title='Name' />" + sEOL;
                    sXML += "    <field width='60' alignH='L' name='Summary' title='Summary' />" + sEOL;
                    sXML += "  </schema>" + sEOL;
                    sXML += "    <render>" + sEOL;
                    sXML += "      <column name='ID'        title='#'          width='6'  alignH='L' />" + sEOL;
                    sXML += "      <column name='Qualifier' title='Qualifier'  width='12' alignH='L' />" + sEOL;
                    sXML += "      <column name='Type'      title='Type'       width='6'  alignH='L' />" + sEOL;
                    sXML += "      <column name='Namespace' title='Namespace'  width='20' alignH='L' />" + sEOL;
                    sXML += "      <column name='Class'     title='Class'      width='20' alignH='L' />" + sEOL;
                    sXML += "      <column name='Name'      title='Name'       width='30' alignH='L' />" + sEOL;
                    sXML += "      <column name='Summary'   title='Summary'    width='60' alignH='L' />" + sEOL;
                    sXML += "    </render>" + sEOL;
                    sXML += "    <fonts>" + sEOL;
                    sXML += "      <font for='tablebody'   typeface='Arial' height='7' bold='n' italic='n' />" + sEOL;
                    sXML += "      <font for='tableheader' typeface='Arial' height='8' bold='y' italic='n' />" + sEOL;
                    sXML += "      <font for='pagefooter'  typeface='Arial' height='6' bold='n' italic='n' />" + sEOL;
                    sXML += "      <font for='pageheader'  typeface='Times' height='7' bold='n' italic='n' />" + sEOL;
                    sXML += "    </fonts>" + sEOL;
                    sXML += "    <report>" + sEOL;
                    sXML += "    <page name='Sample Report' " + sEOL;

                    string sTIME = VVX.File.DoGetLastWriteTime(this.msFileXML);
                    //sTIME = "";

                    sXML += "            header='" + VVX.File.DoExtractFilename(this.msFileXML) + " [" + sTIME + "]'" + sEOL;
                    sXML += "            footer='Page #'" + sEOL;
                    sXML += "            watermarktext=''" + sEOL;
                    sXML += "            watermarkfile=''" + sEOL;
                    sXML += "            pagenumberformat='Page {0}'" + sEOL;
                    sXML += "            pagenumberstart='0'" + sEOL;
                    sXML += "            />" + sEOL;
                    sXML += "    </report>" + sEOL;
                    sXML += "    <credits>" + sEOL;
                    sXML += "      <item text='Created on "+DateTime.Now.ToString()+"'/>" + sEOL;
                    sXML += "      <item text='Using " + msAppName.Trim() + ". " + VVX.About.DoGetCopyright()+ ". All rights reserved.'/>" + sEOL;
                    sXML += "    </credits>" + sEOL; ;

                    for (int row = 0; row < dgv.Rows.Count; row++)
                    {
                        int col = 0;
                        string[] sCols = new string[dgv.ColumnCount];
                        for (col = 0; col < dgv.ColumnCount; col++)
                        {
                            string sVal = dgv.Rows[row].Cells[col].Value.ToString();
                            sCols[col] = sVal.Replace("'", "");
                        }

                        string sFmt = "<member name='{0}' Qualifier='{1}' Type='{2}' Namespace='{3}' Class='{4}' Name='{5}' Summary='{6}'/>";
                        
                        col = 0;
                        string sMember = String.Format(sFmt
                                                        , sCols[col++]
                                                        , sCols[col++]
                                                        , sCols[col++]
                                                        , sCols[col++]
                                                        , sCols[col++]
                                                        , sCols[col++]
                                                        , sCols[col++]
                                                        );
                        sXML += sMember + sEOL;

                    }
                    sXML += "</xmlStore>" + sEOL;

                    try
                    {
                        XmlDocument xDoc = new XmlDocument();
                        xDoc.LoadXml(sXML);

                        xDoc.Save(sFile);

                        bRet = true;
                    }
                    catch (Exception ex)
                    {
                        Debug.Write(sXML);
                        MsgBox.Error("Error in DoExportXmlStore(...)" + ex.Message);
                    }
                }
                else
                {
                    MsgBox.Info("The XmlStore file MUST be different from the app.xml file you opened");
                }
            }

            return bRet;
        }
        #endregion //File Export Helpers


    }

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
An old dog trying to learn new tricks!

Comments and Discussions