Thursday, October 28, 2010

How to change a theme dynamically

We need to assign a theme in the page preInit event to legimately change the theme dynamically.
protected override void OnInit(EventArgs e)
{
    this.Theme = "Blue";
    base.OnInit(e);
}
However there are couple of challanges if you let users to chose the theme. First one is by the pre-init phase, there are not values loaded for page controls has LoadViewState has not yet been executed.
Solution 1: You can use Request.Form[...] collection.
protected override void OnInit(EventArgs e)
{
    string theme = this.Request.Form[ddlTheme.UniqueID];
    if (!string.IsNullOrEmpty(theme))
        this.Theme = theme;
    else
        this.Theme = "Default";
    base.OnInit(e);
}
Solution 2: You can use a Session variable but we have to re-execute the page to see the session variable.
protected override void OnInit(EventArgs e)
{
    string theme = Session["theme"as string;
    if (!string.IsNullOrEmpty(theme))
        this.Theme = theme;
    else
        this.Theme = "Default";
    base.OnInit(e);
}
protected void ddlTheme_SelectedIndexChanged(object sender, EventArgs e)
{
    Session["Theme"] = this.ddlTheme.SelectedValue;
    Server.Transfer("Page.aspx");
}

First request takes long time in a Asp.net web application

Application Pool recycle time interval.
When you deploy an Asp.net web application to IIS, as you already know each application get assigned to an Application Pool. Each application pool has a recycle interval.
InetMgr-> Application Pools -> [your application pool ] -> Advanced Settings

When the application pool execution time exceeds its configured recycle time interval application pools get recycled. When a application pool get recycled all the temporary classes which represents aspx pages need to be recreated and also all the application need re-initialize. This process may cause your uses experience long time delays for the first request to the server.
Application Pool ideal timeout.
Application Pool has ideal timeout, which means if there are no requests to the application pool for a time greater than ideal timeout IIS shutdown the Application Pool to free up resources. Zero means no timeout. So if you experience delays due to ideal timeout, you can disable ideal timeout by setting value to zero. But most of the shared hosts have this value configured to maximize the efficiency of resource utilization.
netMgr-> Application Pools -> [your application pool ] -> Advanced Settings

With asp.net 4.0
When you redeploy the site, it is inevitable for the first request it takes time as application need to re-initialize. Fortunately in Asp.net 4.0 there is a option to wake up an application immediately after you deploy the application.
<applicationpools>
  <add name="MyApplicationPool" startMode="AlwaysRunning" />
</applicationpools>
Please see this section for more information.

Thursday, October 21, 2010

Useful regular expressions

Match style tag in VS:  style=(("(([:b]*[^"]*[\n]*[:b]*)*)")|('(([:b]*[^']*[\n]*[:b]*)*)'))

Sunday, October 17, 2010

How to show budy cursor while processing a request


Please note this example deos not work in Mozilla Firefox.

Demo:

<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
    <script runat="server">
        public void Save(object sender, EventArgs e)
        {
            System.Threading.Thread.Sleep(5000);
            this.lblLastUpdate.Text = DateTime.Now.ToString("hh:mm:ss");
        }
    </script> 
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager runat="server" ID="pageScriptManager">
        </asp:ScriptManager>
        <script language="javascript" type="text/jscript">
            Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function () {
                document.body.style.cursor = "auto";
            });
            Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function () {
                document.body.style.cursor = "wait";
            });
        </script>
        <asp:UpdatePanel runat="server" ID="upnlInsertContent">
            <ContentTemplate>                
                <asp:Button runat="server" ID="btnSave" OnClick="Save" Text="Save" />
                <asp:Label runat="server" ID="lblLastUpdate" />
            </ContentTemplate>
        </asp:UpdatePanel>    
    </form>
</body>
</html>

Page.RegisterRequiresRaiseEvent

When you implement IPostBackEventHanlder RaisePostBackEvent method get automatically get called only if you postback the form with _EVENTTARGET equal to UniqueID of the web control [__doPostBack(‘ctrl001$mybutton1’,’’)].  But if you need to develop complex postback enable control which will invoke the RaisePostBackEvent as a response to custom __EVENTTRAGETs [__doPostBack(‘custom_target’)] not the UniqueID of the control, then you can register the complex postback enable control with Page.RegisterRequiresRaiseEvent

Example 1: This control postback with the __EVENTTARGET, which is equal UniqueID of the control. This picks up the RaisePostBackEvent method automatically. 
public class CustomButton : WebControlIPostBackEventHandler
{
    public event EventHandler Click;
    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.Write(string.Format(
            @"<input type=""button"" name=""{0}"" id=""{1}"" 
                value=""Click"" onclick=""javascript:__doPostBack('{0}','')"" />",
            this.UniqueID, this.ClientID));
    }
    public void RaisePostBackEvent(string eventArgument)
    {
        if (this.Click != null)
            this.Click(thisnew EventArgs());
    }
}
Example 2: This control postback with the __EVENTTARGET which is NOT equal to UniqueID of the control. So RaisePostBackEvent will NOT get raised automatically. Thus we need to call Page.RegisterRequiresRaiseEvent explicitly. However this approach does not pick up the eventArgument from the postback call.
public class ComplexButton : WebControlIPostBackEventHandler
{
    public event EventHandler Click;
    public void RaisePostBackEvent(string eventArgument)
    {
        if (this.Click != null)
            this.Click(thisnew EventArgs());
    }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.Page.RegisterRequiresRaiseEvent(this);
    }
    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.Write("<div>");
        writer.Write(string.Format(
            @"<input type=""button"" name=""{0}"" id=""{1}"" 
                value=""Save"" onclick=""javascript:__doPostBack('{0}','')"" />",
            this.UniqueID + "$Name"this.ClientID + "_Name"));
        writer.Write(string.Format(
            @"<input type=""button"" name=""{0}"" id=""{1}"" 
                value=""Edit"" onclick=""javascript:__doPostBack('{0}','')"" />",
            this.UniqueID + "$Age"this.ClientID + "_Age"));
        writer.Write("</div>");
    }
}

Example 3: If you need to map different buttons inside the same web control to different event, it is better to use same name as the custom controls UniqueID for the __EVENTTARGET and use eventArgument to distinguish which button get clicked.
public class ComplexButton : WebControlIPostBackEventHandler
{
    public event EventHandler Save;
    public event EventHandler Edit;
    public void RaisePostBackEvent(string eventArgument)
    {
        if (string.IsNullOrEmpty(eventArgument)) return;
        if (eventArgument.Equals("Save"))
        {
            if (this.Save != null)
                this.Save(thisnew EventArgs());
        }
        else if (eventArgument.Equals("Edit"))
        {
            if (this.Edit != null)
                this.Edit(thisnew EventArgs());
        }
    }
    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.Write("<div>");
        writer.Write(string.Format(
            @"<input type=""button"" name=""{0}"" id=""{1}"" 
                    value=""Save"" onclick=""javascript:__doPostBack('{0}','Save')"" />",
            this.UniqueID, this.ClientID + "_Name"));
        writer.Write(string.Format(
            @"<input type=""button"" name=""{0}"" id=""{1}"" 
                    value=""Edit"" onclick=""javascript:__doPostBack('{0}','Edit')"" />",
            this.UniqueID, this.ClientID + "_Age"));
        writer.Write("</div>");
    }
}

Page RegisterRequiresPostBack method.

When you implement a custom control, only if you are implementing IPostBackDataHandler, the LoadPostData method get automatically get called only if you add an input control with the same name as the custom control’s UniqueID. If you don’t want to add a input control with a name equal to custom controls UniqueID property, then you can explicitly register custom control to invoke LoadPostData method by registering with RegisterRequiresPostBack(...) method.
Example 1: This control renders an input control with a name equal to custom controls UniqueID property.
public class CustomTextBox : WebControlIPostBackDataHandler
{
    public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        ///
        /// automatically invoked as we have a 
        /// html input control with a name equal to
        /// web controls UniqueID
        ///
        string text = postCollection[postDataKey];
        return true;
    }
    public void RaisePostDataChangedEvent()
    {
            
    }
    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.Write(string.Format("<input type=\"input\" name=\"{0}\" id=\"{1}\" />"this.UniqueID, this.ClientID));
    }
}
Example 2: This control does not render an input control with a name equal to custom controls UniqueID property. Thus we need RegisterRequiresPostBack call in the load method with the parameter of self.
public class ComplexControl : WebControlIPostBackDataHandler
{
    public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        ///
        /// will NOT get automatically invoked 
        /// because we dont have input control with name
        /// equal to web controls UniqueID
        /// THUS we need to RegisterRequiresPostBack call
        /// 
        string name = postCollection[this.UniqueID + "$Name"];
        string age = postCollection[this.UniqueID + "$Age"];
        return true;
    }
    public void RaisePostDataChangedEvent()
    {
 
    }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.Page.RegisterRequiresPostBack(this);
    }
    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.Write("<div>");
        writer.Write(string.Format("Name: <input type=\"input\" name=\"{0}\" id=\"{1}\" />",
                                        this.UniqueID + "$Name"this.ClientID + "_Name"));
        writer.Write(string.Format("Age: <input type=\"input\" name=\"{0}\" id=\"{1}\" />",
                                        this.UniqueID + "$Age"this.ClientID + "_Age"));
        writer.Write("</div>");
    }
}

Saturday, October 16, 2010

How to work with custom post back data and events

  1. What is Page.RegisterRequiresPostBackEvent
  2. What is Page.RegisterRequiresRaiseEvent

How to find outer html content of a specified html tag in html document

string html = @"
    <html xmlns=""http://www.w3.org/1999/xhtml"" >
    <head>
     <title></title>                   
        <script language=""javascript"">
        </script>
     <style type=""text/css"">
     </style>
    </head>
    <body>
     <form target=""_blank"" id=""searchForm"">
      <a href=""Test.aspx"">Back</a>
            <table>
                <tr>
                    <td>Hello</td>
                </tr>
            </table>
            <p>some paragraph</p>
            <table>
                <tr>
                    <td>Hello</td>
                </tr>
            </table>
     </form>
    </body>
    </html>
";
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    List<string> tables = this.GetTags(html, "table"true);
}
protected List<string> GetTags(string html, string tag, bool outerHtml)
{
    List<string> tables = new List<string>();
    int limit = 0, lb = 0, ub = 0, length = 0;
    length = html.Length;
    string startTag = string.Format("<{0}", tag);
    string endTag = string.Format("</{0}", tag);
    string lHtml = html.ToLower();
    do
    {
        int s = html.ToLower().IndexOf(startTag, limit);
        if (s > 0)
        {
            lb = outerHtml ? s : lHtml.IndexOf(">", s) + 1;
            limit = ub = outerHtml 
                ? lHtml.IndexOf(endTag, lb) + endTag.Length + 1 
                : lHtml.IndexOf(endTag, lb) - 1;
            tables.Add(html.Substring(lb, ub - lb));
        }
        else limit = s;
    }
    while (limit > 0);
    return tables;
}

Thursday, October 14, 2010

How to paste Excel data in a web page (any tabular data) using GridView [ IE only ]

Demo:


Markup:
<%@ Page Language="C#" %>
<%@ Register Assembly="ActiveTest" Namespace="ActiveTest" TagPrefix="asp" %>
<html>
<head id="Head2" runat="server">
    <style>
        body { background-color:#eee; }
        div.WorkingArea { border:solid 10px #cccbackground-color:#fffheight:500px; }
    </style>
    <script language="javascript" type="text/javascript">
        function paste() {
            document.getElementById('ClipboardContent').value =
                                        window.clipboardData.getData('Text');
            return (true);
        } 
    </script>
    <script runat="server">
        protected void Paste(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(this.ClipboardContent.Value))
            {
                this.grvData.DataSource = 
                        DataMapper.GetDataTable(this.ClipboardContent.Value, true); ;
                this.grvData.DataBind();
            }
        }        
    </script>
</head>
<body>
    <form id="form2" runat="server">
    <div>
        <asp:Button ID="btnPaste" runat="server" Text="Paste" 
                            OnClick="Paste" OnClientClick="return paste();" />
        <hr />
        <div class="WorkingArea">
            <asp:BulkGridView ID="grvData" runat="server" />
        </div>
        <asp:HiddenField ID="ClipboardContent" runat="server" ClientIDMode="Static" />
    </div>
    </form>
</body>
</html>
DataMapper Class:
public class DataMapper
{
    public const char ColumnDelemiter = '\t';
    public const char RowDelemiter = '\n';
    public static List<T> GetData<T>(string content)
    {
        List<T> value = new List<T>();
        T obj;
        string[] rowValues;
        string[] colValues;
        int colIndex = 0;
        PropertyInfo pInfo;
        if (string.IsNullOrEmpty(content) || content == "null")
            return null;
        content = content.Replace("\r""");
        rowValues = content.Split(RowDelemiter);
        foreach (string rowItem in rowValues)
        {
            if (string.IsNullOrEmpty(rowItem))
                continue;
 
            colValues = new string[rowItem.Split(ColumnDelemiter).Length];
            colIndex = 0;
            obj = (T)Activator.CreateInstance(typeof(T));
 
            foreach (string colItem in rowItem.Split(ColumnDelemiter))
            {
                pInfo = obj.GetType().GetProperties()[colIndex];
                pInfo.SetValue(obj, colItem, null);
                colIndex++;
            }
            value.Add(obj);
        }
 
        return value;
    }
    public static DataTable GetDataTable(string content, bool IsFirstColumnHeader)
    {
        DataTable value = new DataTable();
        string[] rowValues;
        string[] colValues;
        int colIndex = 0;
        int rowIndex = 0;
 
        if (string.IsNullOrEmpty(content) || content == "null")
            return null;
 
        content = content.Replace("\r""");
        rowValues = content.Split(RowDelemiter);
 
        foreach (string rowItem in rowValues)
        {
            if (string.IsNullOrEmpty(rowItem))
                continue;
 
            colValues = new string[rowItem.Split(ColumnDelemiter).Length];
            colIndex = 0;
 
            foreach (string colItem in rowItem.Split(ColumnDelemiter))
            {
                if (rowIndex == 0 && IsFirstColumnHeader)
                    value.Columns.Add(colItem);
                else if (rowIndex == 0)
                    value.Columns.Add();
 
                if ((rowIndex == 0 && !IsFirstColumnHeader) || rowIndex != 0)
                    colValues[colIndex] = colItem;
 
                colIndex++;
            }
            if ((rowIndex == 0 && !IsFirstColumnHeader) || rowIndex != 0)
                value.Rows.Add(colValues);
 
            rowIndex++;
        }
 
        return value;
    }
}
BulkGridView Control:
namespace ActiveTest
{
    public class BulkGridView : GridView
    {
        protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex,
                                                    DataControlRowType rowType, DataControlRowState rowState)
        {
            return base.CreateRow(rowIndex, dataSourceIndex, rowType, rowState | DataControlRowState.Edit);
        }
    }
}


References
Many thanks for these people for their work.
Real World GridView: Bulk Editing - By Mattdotson
Copy And Paste Excel / Clipboard Data To Gridview In ASP.net - By Jebarson

How to highlight invalid controls on a postback with asp.net validation controls


Demo:
On Load method, first of anything I validate the page because then only all the validators get their IsValid property set up. Then iterate though the page validator collection (Page.Validators) and because this simple demonstration is only for required field validators, I caste the validator to a RequiredFieldValidator.
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    if (this.IsPostBack)
    {
        this.Validate();
        foreach (object v in this.Validators)
        {
            if (v is RequiredFieldValidator)
            {
                RequiredFieldValidator r = v as RequiredFieldValidator;
                TextBox t = this.FindField(this.Page.Form, r.ControlToValidate) as TextBox;
                if (t != null)
                {
                    if (r.IsValid)
                        t.BackColor = System.Drawing.Color.Green;
                    else
                        t.BackColor = System.Drawing.Color.Red;
                }
 
            }
        }
    }
}
Then the most interesting bit is the The FindField(...) method. You may ask why we can’t use FindControl(...) method. The problem is it works when you work with simple page where you have controls directly in the form it works, but when it comes to complex pages with master pages and content place holders, FindControl(...) didn’t work. So I implemented a recursive method which grills down in the control hierarchy and find the control. I start with this.Page.Form as for sure we know we can’t put form related controls outside the form control. What it all does it find the control in its first level controls (Controls collection) and if it can’t find the given control by its id, it go thorough it’s child control collection and recursively try to find the control. If it finds the control return the found control immediately, if not keep looking. Finally if you still can’t find the control return null. 
private Control FindField(Control source, string id)
{
    Control target = source.FindControl(id);
    if (target != nullreturn target;
    foreach (Control child in source.Controls)
    {
        target = this.FindField(child, id);
        if (target != nullreturn target;
    }
    return null;
}
Put them all together,
Complete Example:
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
    <script runat="server">
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (this.IsPostBack)
            {
                this.Validate();
                foreach (object v in this.Validators)
                {
                    if (v is RequiredFieldValidator)
                    {
                        RequiredFieldValidator r = v as RequiredFieldValidator;
                        TextBox t = this.FindField(this.Page.Form, r.ControlToValidate) as TextBox;
                        if (t != null)
                        {
                            if (r.IsValid)
                                t.BackColor = System.Drawing.Color.Green;
                            else
                                t.BackColor = System.Drawing.Color.Red;
                        }
 
                    }
                }
            }
        }
        private Control FindField(Control source, string id)
        {
            Control target = source.FindControl(id);
            if (target != nullreturn target;
            foreach (Control child in source.Controls)
            {
                target = this.FindField(child, id);
                if (target != nullreturn target;
            }
            return null;
        }
        protected void Save(object sender, EventArgs e)
        {
 
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        Name: <asp:TextBox runat="server" ID="txtName" />
        <asp:RequiredFieldValidator runat="server" ID="rvalName" ControlToValidate="txtName" 
                                    ErrorMessage="Name is required" EnableClientScript="false" /><br />
        Address: <asp:TextBox runat="server" ID="txtAddress" />
        <asp:RequiredFieldValidator runat="server" ID="rvalAddress" ControlToValidate="txtAddress" 
                                    ErrorMessage="Address is required" EnableClientScript="false" /><br />
        Phone: <asp:TextBox runat="server" ID="txtPhone" />
        <asp:RequiredFieldValidator runat="server" ID="rvalPhone" ControlToValidate="txtPhone" 
                                    ErrorMessage="Phone is required" EnableClientScript="false" /><br />
        <hr />
        <asp:Button runat="server" ID="btnSave" OnClick="Save" Text="Save" />
    </form>
</body>
</html>

Wednesday, October 13, 2010

How to validate a CSV file while importing to a SQL table

This post is based on How to import CSV or Text file to SQL table using SqlBulkCopy in C#, which contain all the explanation about the data import validating excising records and bulk import.

Validating file schema is the next hurdle. For this I have imported the Importer’s column mapping class to handle column type and column width. So that invalid file will be thrown out with an exception.
Based on the table, 
I add column mappings with column types and widths of text fields
///
/// Set column mappings
///
importer.DateTimeFormat = "dd-MMM-yyyy";
importer.ColumnMappings.Add(new ColumnMapping("Id""Id"DataType.Short));
importer.ColumnMappings.Add(new ColumnMapping("Name""Name"DataType.Text, 50));
importer.ColumnMappings.Add(new ColumnMapping("Grade""Grade"DataType.Text, 3));
 Will create a schema file like this,
When we input a CSV file in correct format like this
Importer will import the file. But an Invalid file like this will be thrown with an exception.

Full example
Mark-up:
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
</head>
<body>
    <form id="form1" runat="server">
        <asp:FileUpload runat="server" ID="fuFile" />
        <asp:Button runat="server" ID="btnImport" OnClick="Import" Text="Import" />
        <asp:DropDownList runat="server" ID="ddlFileType">
            <asp:ListItem Value="CSV" Selected="True">CSV Delimited</asp:ListItem>
            <asp:ListItem Value="TAB">Tab Delimited</asp:ListItem>
        </asp:DropDownList>
    </form>
</body>
</html>
Code:
namespace ActiveTest
{
    public partial class Test : Page
    {
        protected void Import(object sender, EventArgs e)
        {
            String path = Server.MapPath("~/Data/");
            try
            {
                if (this.fuFile.HasFile)
                {
                    /// 
                    /// Upload file
                    ///
                    string fileName = this.fuFile.FileName;
                    string fullName = Path.Combine(path, fileName);
                    if (File.Exists(fullName)) File.Delete(fullName);
                    this.fuFile.PostedFile.SaveAs(fullName);
                    ///
                    /// Instantiate DelimitedDataImporter and set connection string
                    ///
                    DelimiterType type = DelimiterType.CsvDelimited;
                    if (this.ddlFileType.SelectedValue.Equals("TAB")) type = DelimiterType.TabDelimited;
                    DelimitedFileImporter importer = new DelimitedFileImporter(type);
                    importer.ConnectionString =
                        ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                    ///
                    /// Find existing records and set filter statement [OPTIONAL]
                    ///
                    StringBuilder sb = new StringBuilder(string.Empty);
                    using (SqlConnection con = new SqlConnection(
                        ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
                    {
                        SqlCommand cmd = new SqlCommand("SELECT Id FROM Student", con);
                        con.Open();
                        SqlDataReader reader = cmd.ExecuteReader();
                        while (reader.Read())
                            sb.AppendFormat("{0},", reader.GetInt32(0).ToString());
                        reader.Close();
                        con.Close();
                    }
                    string ids = string.Empty;
                    if (!string.IsNullOrEmpty(sb.ToString())) ids = sb.ToString().Remove(sb.Length - 1, 1);
                    if (!string.IsNullOrEmpty(ids)) importer.Filter =
                        string.Format("Id NOT IN ({0})", ids);
                    ///
                    /// Set column mappings
                    ///
                    importer.DateTimeFormat = "dd-MMM-yyyy";
                    importer.ColumnMappings.Add(new ColumnMapping("Id""Id"DataType.Short));
                    importer.ColumnMappings.Add(new ColumnMapping("Name""Name"DataType.Text, 50));
                    importer.ColumnMappings.Add(new ColumnMapping("Grade""Grade"DataType.Text, 3));
                    ///
                    /// Import data to sql table
                    ///
                    importer.ImportToDatabase(fullName, "Student");
                }
            }
            catch
            {
                throw new Exception("Import Faild");
            }
        }      
    }
 
    #region EventArgs Specification
 
    public enum DelimiterType
    {
        TabDelimited,
        CsvDelimited,
        CustomDelimited
    }
    public class ImportDelimitedEventArgs : EventArgs
    {
        private ReadOnlyCollection<object> content;
        private int lineNumber;
 
        public ImportDelimitedEventArgs(OleDbDataReader reader, int number)
        {
            object[] columns = new object[reader.FieldCount];
            reader.GetValues(columns);
            content = new ReadOnlyCollection<object>(columns);
            lineNumber = number;
        }
        public bool BreakImport { getset; }
        public int LineNumber
        {
            get { return lineNumber; }
        }
        public ReadOnlyCollection<object> Content
        {
            get { return content; }
        }
    }
 
    #endregion
 
    #region Mappings
 
    public class ColumnMapping
    {
        public string SourceColumn { getset; }
        public string DestinationColumn { getset; }
        public DataType Type { getset; }
        public int Width { getset; }
        public bool IsValidatble { getset; }
        public ColumnMapping(string sourceColumn, string destinationColumn)
        {
            this.SourceColumn = sourceColumn;
            this.DestinationColumn = destinationColumn;
        }
        public ColumnMapping(string sourceColumn, string destinationColumn, DataType type)
        {
            this.SourceColumn = sourceColumn;
            this.DestinationColumn = destinationColumn;
            this.Type = type;
            if (this.Type == DataType.Text)
                throw new ArgumentNullException("Width should be specified when the data type is Text");
            this.IsValidatble = true;
        }
        public ColumnMapping(string sourceColumn, string destinationColumn, DataType type, int width)
        {
            this.SourceColumn = sourceColumn;
            this.DestinationColumn = destinationColumn;
            this.Type = type;
            this.Width = width;
            this.IsValidatble = true;
        }
    }
    public class ColumnMappingCollection : List<ColumnMapping>
    {
        public bool IsValidatable
        {
            get
            {
                foreach (ColumnMapping m in this) 
                    if (!m.IsValidatble) return false;
                return true;
            }
        }
        public bool HasDateFields
        {
            get
            {
                foreach (ColumnMapping m in thisif (m.Type == DataType.DateTime) return true;
                return false;
            }
        }
    }
 
    #endregion
 
    #region Types
 
    public enum DataType
    {
        Bit,
        Byte,
        Short,
        Long,
        Currency,
        Single,
        Double,
        DateTime,
        Text,
        Memo
    }
 
    #endregion
 
    #region Importer
 
    public class DelimitedFileImporter
    {
        #region Event handler
 
        public event EventHandler<ImportDelimitedEventArgs> ProcessLine;
        private bool HandleLine(OleDbDataReader reader, int number)
        {
            bool result = true;
            EventHandler<ImportDelimitedEventArgs> temp = ProcessLine;
            if (temp != null)
            {
                ImportDelimitedEventArgs args = new ImportDelimitedEventArgs(reader, number);
                temp(this, args);
                result = !args.BreakImport;
            }
            return result;
        }
 
        #endregion
 
        #region Constructors
 
        public DelimitedFileImporter()
            : this(DelimiterType.TabDelimited, null)
        {
            this.Initialize();
        }
        public DelimitedFileImporter(DelimiterType delimiter)
            : this(delimiter, null)
        {
            this.Initialize();
        }
        public DelimitedFileImporter(DelimiterType delimiterType, string delimiter)
        {
            this.Delimiter = delimiterType;
            this.CustomDelimiter = delimiter;
            this.Initialize();
        }
        private void Initialize()
        {
            this.ColumnMappings = new ColumnMappingCollection();
        }
 
        #endregion
 
        #region Properties
 
        public DelimiterType Delimiter { getset; }
        public string CustomDelimiter { get;set;}
        public string Filter { getset; }
        public string ConnectionString { getset; }
        public string DateTimeFormat { getset; }
        public ColumnMappingCollection ColumnMappings { getset; }
 
        #endregion
 
        #region Methods
 
        public void ImportToDatabase(string fileName, string tableName)
        {
            if (string.IsNullOrEmpty(this.ConnectionString))
                throw new ArgumentNullException("Connection String");
            FileInfo file = new FileInfo(fileName);
            WriteSchemaIniFile(file);
            using (OleDbConnection con = JetConnection(file))
            {
                using (OleDbCommand cmd = JetCommand(file, con))
                {
                    con.Open();
                    using (OleDbDataReader reader = cmd.ExecuteReader())
                    {
                        SqlBulkCopy sqlBulk = new SqlBulkCopy(this.ConnectionString);
                        sqlBulk.DestinationTableName = tableName;
                        foreach (ColumnMapping map in this.ColumnMappings)
                            sqlBulk.ColumnMappings.Add(map.DestinationColumn, map.SourceColumn);
                        sqlBulk.WriteToServer(reader);
                    }
                }
            }
        }
        private OleDbConnection JetConnection(FileInfo file)
        {
            StringBuilder connection = new StringBuilder("Provider=Microsoft.Jet.OLEDB.4.0");
            connection.AppendFormat(";Data Source=\"{0}\"", file.DirectoryName);
            connection.Append(";Extended Properties='text;HDR=Yes");
            if (this.Delimiter == DelimiterType.CustomDelimited)
            {
                if (this.CustomDelimiter == null)
                    throw new InvalidOperationException("Custom delimiter is not specified");
                connection.AppendFormat(";FMT=Delimited({1})"this.CustomDelimiter);
            }
            connection.Append("';");
            return new OleDbConnection(connection.ToString());
        }
        private OleDbCommand JetCommand(FileInfo file, OleDbConnection con)
        {
            StringBuilder commandText = new StringBuilder("SELECT * FROM ");
            commandText.AppendFormat("[{0}]", file.Name);
            if (this.Filter != null)
            {
                commandText.Append(" WHERE ");
                commandText.Append(this.Filter);
            }
            OleDbCommand cmd = new OleDbCommand(commandText.ToString(), con);
            cmd.CommandTimeout = 60000;
            return cmd;
        }
        private void WriteSchemaIniFile(FileInfo file)
        {
            string schema = Path.Combine(file.DirectoryName, "Schema.ini");
            if (!File.Exists(schema)) File.Delete(schema);
            using (StreamWriter writer = new StreamWriter(schema))
            {
                writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "[{0}]", file.Name));
                if (this.ColumnMappings.IsValidatable) writer.WriteLine("ColNameHeader=True");             
                switch (this.Delimiter)
                {
                    case DelimiterType.CustomDelimited:
                        writer.WriteLine(string.Format(CultureInfo.InvariantCulture,
                            "Format=Delimited({0})"this.CustomDelimiter));
                        break;
                    case DelimiterType.CsvDelimited:
                    case DelimiterType.TabDelimited:
                    default:
                        writer.WriteLine(string.Format(CultureInfo.InvariantCulture,
                            "Format={0}"this.Delimiter));
                        break;
                }
                if (this.ColumnMappings.HasDateFields)
                {
                    if (string.IsNullOrEmpty(this.DateTimeFormat))
                        throw new ArgumentNullException("DateTimeFormat missing");
                    else
                        writer.WriteLine(string.Format(CultureInfo.InvariantCulture, 
                            "DateTimeFormat={0}"this.DateTimeFormat));
                }
                if (this.ColumnMappings.IsValidatable)
                {
                    foreach (ColumnMapping m in this.ColumnMappings)
                    {
                        writer.WriteLine("Col{0}={1} {2}{3}", 
                            this.ColumnMappings.IndexOf(m) + 1, m.SourceColumn, 
                                m.Type, m.Type == DataType.Text ? " Width " + m.Width.ToString() : string.Empty);
                    }
                }
            }
        }
 
        #endregion
    }
 
    #endregion
}

iPhone Launch Screen Sizes

iPhone Portrait iOS 8 Retina HT 5.5 = 1242 X 2208 Retna HD 4.7 = 750 X 1134 iPhone Landscape iOS 8 Retina HD 5.5  2208 X 1242 iPho...