Tuesday 7 February 2012

Validate DetailView Control (ASP.NET, C#)

Problem
I use the DetailView Control connected to a DataSource to let the user insert new data. The DetailView Control has two fields: CustomerName and CustomerEmail. I have to control the user input to avoid invalid data or fields empty.


Impact
The application gets no values or invalid data, it will cause an error when you insert a new record in the database due to requiements of the fields in the database.



Solution
Use Validation Controls: RequiredFieldValidator (to ensure that a value has been provided) and RegularExpressionValidator (to validate a value against a regular expression). To add validation controls to the inserting interface, the BoundFields used by the DetailsView control need to be converted into TemplateFields. To achieve this, click on the Edit Fields link in the DetailsView's smart tags.

After the TextBox in the  CustomerName EditItemTemplate, add a RequiredFieldValidator by dragging it from the Toolbox into the template-editing interface. Repeat the steps for CustomerEmail. Next, set each RequiredFieldValidator's ControlToValidate property to InsertCustomerName and InsertCustomerEmail, respectively. Finally, set the ErrorMessage property to "e field is required." and the Text property to "*". (if the Text property value is omitted, the ErrorMessage property value is also the text displayed by the validation control on invalid input).

Placing after the RequiredFieldValidator for CustomerEmail, , add also a RegularExpressionValidator, and set the ControlToValidate property to InsertCustomerEmail, its ErrorMessage property to "The email is not valid.", and its Text property to "*".


Code
<Fields>    <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
    <asp:TemplateField HeaderText="Customer Name" SortExpression="CustomerName">
         <InsertItemTemplate>
              <asp:TextBox ID="InsertCustomerName" runat="server" Text='<%# Bind("CustomerName") %>'></asp:TextBox>
              <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="InsertCustomerName"
                ErrorMessage="Customer Name is required." Display="Dynamic">*
              </asp:RequiredFieldValidator>
         </InsertItemTemplate>
    </asp:TemplateField>

    <asp:TemplateField HeaderText="Customer Email" SortExpression="CustomerEmail">
         <InsertItemTemplate>
              <asp:TextBox ID="InsertCustomerEmail" runat="server" Text='<%# Bind("CustomerEmail") %>'></asp:TextBox>
              <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ControlToValidate="InsertCustomerEmail"
                 ErrorMessage="Customer Email is required." Display="Dynamic">*
              </asp:RequiredFieldValidator>
              <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="InsertCustomerEmail"
                ErrorMessage="Customer Email is not valid." ValidationExpression='\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*' Display="Dynamic">*
              </asp:RegularExpressionValidator>
         </InsertItemTemplate>
     </asp:TemplateField>
     <asp:CommandField ShowInsertButton="True" />

</Fields


Conclusion
To ensure that the user enters required inputs in a correct format in the inserting interface of the DetailView Control, you should convert the BoundFields into TemplateFields and add the Validation Controls to the appropriate template(s).

Monday 6 February 2012

WebBrowser Example

This an example of the Web Browser Control using Windows Form Application Framework 3.5. One of the primary demands for the UI is the ability to have only a single instance of the application running but to be able to have multiple Web pages open that the user can rapidly switch between without having to navigate back and forth.


The goals of this component are:

  • Implementing the WebBrowser Control
  • Having the following button: back, forward, home, refresh and stop
  • Being able to bookmark the web page (Favorite)
  • Being able to have multiple Web pages open that the user can rapidly switch between without having to navigate back and forth (Use container controls)
In the next section, I will explain the coding details in a short form.

Implementing the WebBrowser Control
In the implementation of the Web Browser, I use a Tab Control, that I explain below. In the TabPage I will load each website. In the project I give an option to add new tab, or close tab.
private void NewWeb()
{    // Add a new tab control, and load the web control in it.
    // Define a maxium of 5 tabs, you can change the number.
    if (currentTabCount == 5) return;
   
    // Create the new tab page
    TabPage newpage = new TabPage("Loading...");  
    tabControl1.TabPages.Add(newpage);               
    // Keep track of how many pages are open.
    currentTabCount++;
    // Create a new WebBrowser control.
    WebBrowser webpage = new WebBrowser();        
    webPages.Add(webpage);
    webpage.Parent = newpage;
    webpage.Dock = DockStyle.Fill;

     // When the site has been displayed, and updated the name of the Tab with the site title.
     webpage.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webpage_DocumentCompleted);
     // Select the new site as the foreground
     tabControl1.SelectedTab = newpage;
}


Have the following button: back, forward, home, refresh and stop
I use the toolStripButton control where I place all the button for the browser. It gives facilities to add an image and/or a text. In the code-behing, I implemented these snipets.

private  void toolStripButtonForward_Click(object sender, EventArgs e)
{  
    // Go Forward - if the web control can go back.
    WebBrowser thiswebpage = GetCurrentWebBrowser();
    if (thiswebpage.CanGoForward)
        thiswebpage.GoForward();
}

private void toolStripButtonBack_Click(object sender, EventArgs e)
{    // Go Back - if the web control can go back.
    WebBrowser thiswebpage = GetCurrentWebBrowser();
     if (thiswebpage.CanGoBack)
        thiswebpage.GoBack();
}

private void toolStripButtonGoHome_Click(object sender, EventArgs e)
{    // Go Home - go to the default home page.
    toolStripComboBox1.Text = "about:blank";
    // Update the Tab Control too
    tabControl1.SelectedTab.Text = "Blank Page";
   WebBrowser thiswebpage = (WebBrowser)webPages[tabPages.IndexOf(tabControl1.SelectedTab)];  
    thiswebpage.Navigate("about:blank");}

private void toolStripButtonRefresh_Click(object sender, EventArgs e)
{    // Refresh - cause the browser to reload and redisplay the current page
    WebBrowser thiswebpage = GetCurrentWebBrowser();
     thiswebpage.Refresh();
}

private void toolStripButtonStop_Click(object sender, EventArgs e)
{
    
WebBrowser thiswebpage = GetCurrentWebBrowser();
     thiswebpage.Stop();
}

Being able to bookmark the web page (Favorite)
In this case, I use a TreeView Control to bookmark my favorites pages. By default, the root is named Favorites, but you can create your own groups. I created another form and the user can select the node to save the page.

private void toolStripButtonAddFavorite_Click(object sender, EventArgs e)
{    
      if (GetCurrentWebBrowser().Url != null)
     {
         // Show the AddFavorites dialog
         AddFavorites dlgFavorite = new AddFavorites(GetCurrentWebBrowser().Url.ToString());
         TreeNodeCollection nodes = this.treeViewFavorite.Nodes;
       foreach (TreeNode node in nodes)
           dlgFavorite.comboBoxFFolder.Items.Add(node.Text);
      DialogResult resFavorite = dlgFavorite.ShowDialog();
      bool findNode = false;

       // If the user clicks OK
      if (resFavorite == DialogResult.OK)
     {
           
        if (dlgFavorite.comboBoxFFolder.Text.Equals("Favorites"))
        {
             TreeNode newChild = new TreeNode(dlgFavorite.textBoxFName.Text);
             treeViewFavorite.Nodes[0].Nodes.Add(newChild);
             newChild.ToolTipText = dlgFavorite.textBoxFName.Text;
             treeViewFavorite.ExpandAll();
         }
         else
        {
             // Search if the node exists, add the child
             foreach (TreeNode node in treeViewFavorite.Nodes)
             {
                 if (node.Text == dlgFavorite.comboBoxFFolder.Text)
                {
                    // Node exist, add the new child
                    node.Nodes.Add(new TreeNode(dlgFavorite.textBoxFName.Text));
                    node.ToolTipText = dlgFavorite.textBoxFName.Text;
                    treeViewFavorite.ExpandAll();
                    findNode = true;
                    break;
                }
            }
            if (!findNode)
            {               
                // Node doen't exists, add the parent Node and the child
               TreeNode newNode = new TreeNode(dlgFavorite.comboBoxFFolder.Text);
               TreeNode newChild = new TreeNode(dlgFavorite.textBoxFName.Text);

               newNode.Nodes.Add(newChild);
               newChild.ToolTipText = dlgFavorite.textBoxFName.Text;
               treeViewFavorite.Nodes.Add(newNode);
               treeViewFavorite.ExpandAll();
           }

           dlgFavorite.Close();
       }
     }
   }
}

Being able to have multiple Web pages open
I use in the project a TabControl that allow the user rapidly switch between  sites without having to navigate back and forth. The code to use is below.

private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{    if (GetCurrentWebBrowser().Url != null)
         toolStripComboBox1.Text = GetCurrentWebBrowser().Url.ToString();
}


private WebBrowser GetCurrentWebBrowser()
{
    
// This method returns the currently display WebControl, use
    // an array to find the active one by getting the index of the current tab.
    TabPage current_tab = tabControl1.SelectedTab;
    WebBrowser thiswebpage = (WebBrowser)webPages[tabPages.IndexOf(current_tab)];
    return thiswebpage;
}

The sample application and source
The sample application demonstrate the use of differents controls to show the WebBrowser Control functionality. The code is commented, and hopefully gives enough information for helping you put your own solution together. I am able to shareand email you all the source, please let me know.

This is my first blog. Thanks for reading! If you can add any comment or have suggestions or tips, please post a message below.  I would appreciate that.

 

About the Author:

Jenny Coca
. NET Software/Web Developer
I was born in Havana, Cuba
I live in Toronto, Canada
Microsoft Certified Professional Developer (Windows and Web)
MCITP on Microsoft SQL Server 2005 (Database Developer and Administrator)
I work with C#, VB.Net and PHP
Share is the key!