C#: Save a Form’s Size and Location

In an attempt to enhance user experience it may be desirable to save the size and location of a Form. When dealing with customizable user settings, it is important to determine where to persist the user’s applications settings. The Application class has a UserAppDataRegistry property that references the HKEY_CURRENT_USER\Software\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion]. registry key in the user’s profile (If this key does not exist it is created). Here is a basic example of storing a form's state in the user's registry profile:
	private void Form_Load(object sender, EventArgs e)
        {
            this.WindowState = (FormWindowState)FormWindowState.Parse(WindowState.GetType(), Application.UserAppDataRegistry.GetValue("WindowState", FormWindowState.Normal).ToString());
            if (this.WindowState == FormWindowState.Normal)
            {
                int x = (int)Application.UserAppDataRegistry.GetValue("LocationX");
                int y = (int)Application.UserAppDataRegistry.GetValue("LocationY");
                this.DesktopLocation = new Point(x, y);
                int w = (int)Application.UserAppDataRegistry.GetValue("WindowSizeW");
                int h = (int)Application.UserAppDataRegistry.GetValue("WindowSizeH");
                this.Size = new Size(w, h);
            }
        }

        private void Form_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.UserAppDataRegistry.SetValue("WindowState", this.WindowState);
            Application.UserAppDataRegistry.SetValue("WindowSizeH", this.Size.Height);
            Application.UserAppDataRegistry.SetValue("WindowSizeW", this.Size.Width);
            Application.UserAppDataRegistry.SetValue("LocationX", this.DesktopLocation.X);
            Application.UserAppDataRegistry.SetValue("LocationY", this.DesktopLocation.Y);
        }



   

ASP.NET Membership Using a Custom Profile

ASP.NET Membership Custom Profile

The ASP.NET Membership is an easy way to manage user credentials and security within ASP.NET Web Application (Web Site).  ASP.NET Membership will not only handle user authentication, it can also be used to manage user profile information.  To add a Custom Profile for the ASP.NET Membership users you need to enable profiles, specify a profile provider and add the profile properties in the system.web section of the web.config file:
<profile enabled="true">
			<providers>
				<remove name="AspNetSqlProfileProvider"/>
				<add name="AspNetSqlProfileProvider" connectionStringName="SqlMembership" applicationName="appProfile" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
			</providers>
			<properties>
				<add name="Gender" type="System.String"/>
				<add name="favoritenumber" type="System.Int32"/>
				<add name="notification" type="System.Boolean"/>
				<add name="BirthDate" type="System.DateTime"/>
			</properties>
		</profile>
Once the profile information has been enable and configured a user’s profile information can be read and saved through the dynamic ProfileCommon class. The ProfileCommon class will the properties specified in the configuration file.  A simplified code example for reading and saving profile values:
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            if (User.Identity.IsAuthenticated == true)
            {
                MembershipUser user = Membership.GetUser();
                ((TextBox)LoginView1.FindControl("Email")).Text = ((TextBox)LoginView1.FindControl("Email2")).Text = user.Email;
                ((TextBox)LoginView1.FindControl("txtNumber")).Text = Profile.favoritenumber.ToString();
                DropDownList ddl = (DropDownList)LoginView1.FindControl("ddlGender");
                ddl.SelectedIndex = ddl.Items.IndexOf(ddl.Items.FindByValue(Profile.Gender));
                ((CheckBox)LoginView1.FindControl("chkNotification")).Checked = Profile.notification;
            }
        }
    }

    protected void btnSave_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            TextBox Email;
            MembershipUser user = Membership.GetUser();
            Email = (TextBox)LoginView1.FindControl("Email");
            if (user.Email != Email.Text)
            {
                user.Email = Email.Text;
            }
            Membership.UpdateUser(user);
            
            Profile.Gender = ((DropDownList)LoginView1.FindControl("ddlGender")).SelectedValue;
            Profile.notification = ((CheckBox)LoginView1.FindControl("chkNotification")).Checked;
            Profile.favoritenumber = System.Convert.ToInt32(((TextBox)LoginView1.FindControl("txtNumber")).Text);
            Profile.Save();
        }
    }

ASP.NET Membership Custom Profile



   

ASP.NET GridView: Multiple Column Sort

The native ASP.NET GridView allows for the sorting of data by setting the Grid's AllowSorting property to True.  With AllowSorting enabled, header row cells contain hyperlinks, which when clicked, sort the GridView.  There are several GridView properties and events available which can be used for the customization of the GridView's sort.

  • The Sort method, defined as Sort ( string sortExpression, SortDirection sortDirection ), sorts the GridView based upon the specified sort expression and direction.
  • The Sorting event occurs when the hyperlink column heading is clicked, but before the GridView has handled the sorting of the data.
  • The Sorted event occurs when the hyperlink column heading is clicked, but after the GridView has sorted the datasource.
  • The RowCreated event occurs when a row is created in the GridView.
  • The SortDirection property gets the sort direction of the column being sorted.
  • The SortExpression property gets the sort expression associated with the column being sorted.



The default sort action of the GridView sorts only by a single column.  Using the available sort related events and properties it is rather easy to create a GridView that can be sorted by multiple columns.  The following example is for a GridView than can be sorted by multiple columns.  In this example the columns are sorted in the order they are clicked by a tri-state function.  Clicking on a column heading will set a columns sort state to be Ascending, Descending or Off.  The columns in the GridView are sorted based upon in which they are click or turned on.  When the sort state of a column is Off it is removed from the sort.

using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

/// <summary>
/// MySortItem is a class that is used to in a List to store the sort columns and thier order
/// </summary>
public class MySortItem
{
    private string columnname;
    public string ColumnName
    {
        get
        {
            return columnname;
        }
        set
        {
            columnname = value;
        }
    }
    private SortDirection columnsort;
    public SortDirection ColumnSort
    {
        get
        {
            return columnsort;
        }
        set
        {
            columnsort = value;
        }
    }
    public string SortToString( SortDirection cs )
    {
        string s = ( cs == SortDirection.Ascending ) ? "asc" : "desc";
        return s;
    }

}

public partial class _Default : System.Web.UI.Page
{
    DataSet ds = new DataSet ();
    // List for holding sorted columns, their order and their direction
    List<MySortItem> sl;

    protected void Page_Load( object sender, EventArgs e )
    {
        // If the Column Sort List does not exist, create it. the list is stored in a session variable
        if ( Session["sortitems"] == null )
        {
            Session["sortitems"] = new List<MySortItem> ();
        }
        sl = (List<MySortItem>) Session["sortitems"];

        if ( !Page.IsPostBack )
        {
            // Procedure for binding the datasource with the DataGrid
            BindDataGrid ( GridView1 );
        }
    }

    /// <summary>
    /// Called from within the application to Bind the DataGrid to a datasource. in this cases it is the default view of a table. 
    /// </summary>
    /// <param name="gv"></param>
    protected void BindDataGrid( GridView gv )
    {
        // Read data from an XML file
        ds.ReadXml ( Server.MapPath ( "~/App_Data/Data.xml" ) );

        // build the sort expression
        string sortexp = "";
        for ( int i = 0; i < sl.Count; i++ )
        {
            sortexp = ( i == 0 ) ? sl[i].ColumnName + " " + sl[i].SortToString ( sl[i].ColumnSort ) : sortexp + "," + sl[i].ColumnName + " " + sl[i].SortToString ( sl[i].ColumnSort );
        }

        //Set label text to display the sort expression on the page for the user
        Label3.Text = sortexp;
        // set the datasource's table default view to indicate sorting; a datatable could also be used directly. In this example a datasource
        // was used due to dynmaic XML data loading
        ds.Tables[0].DefaultView.Sort = sortexp;
        // set the datagrid's datasource
        gv.DataSource = ds.Tables[0].DefaultView;
        gv.DataBind ();
    }

    /// <summary>
    /// Assigned to the GridView's PagIndexChanging event. This is used if the GridView allows for paging. 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void GridView1_PageIndexChanging( object sender, GridViewPageEventArgs e )
    {
        try
        {
            if ( sender is GridView )
            {
                ( (GridView) sender ).PageIndex = e.NewPageIndex;
                BindDataGrid ( GridView1 );
                e.Cancel = false;
            }
        }
        catch
        {

            e.Cancel = true;
        }
    }

    /// <summary>
    /// Assigned to the GridView's Sorting event. 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void GridView1_Sorting( object sender, GridViewSortEventArgs e )
    {
        try
        {
            // Scroll through the list and see if the clicked GridView column exists in the sort list.
            // If there is an entry for the column then change the order or remove the column from the list (tri-state)
            bool found = false;
            for ( int i = 0; i < sl.Count; i++ )
            {
                if ( sl[i].ColumnName == e.SortExpression.ToString () )
                {
                    found = true;
                    switch ( sl[i].ColumnSort )
                    {
                        case SortDirection.Descending:
                            sl[i].ColumnSort = SortDirection.Ascending;
                            break;
                        case SortDirection.Ascending:
                            sl.RemoveAt ( i );
                            break;
                    }
                }
            }
            if ( !found )
            {
                MySortItem si = new MySortItem ();
                si.ColumnName = e.SortExpression.ToString ();
                si.ColumnSort = SortDirection.Descending;
                sl.Add ( si );
            }

            BindDataGrid ( GridView1 );
            //accept column sort
            e.Cancel = false;
        }
        catch ( Exception )
        {
            //error so cancel
            e.Cancel = true;
        }
    }

    /// <summary>
    /// Assigned to the GridView's RowCreated event.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void GridView1_RowCreated( object sender, GridViewRowEventArgs e )
    {
        // add images to the column header to indicate sort of each column
        if ( e.Row.RowType == DataControlRowType.Header )
        {
            foreach ( TableCell tc in e.Row.Cells )
            {
                if ( tc.HasControls () )
                {
                    // search for the header link
                    LinkButton lnk = (LinkButton) tc.Controls[0];
                    if ( ( lnk != null ) & ( sl != null ) )
                    {
                        // Get the position of the column in the List 
                        int i = sl.FindIndex ( delegate ( MySortItem s )
                        {
                            return s.ColumnName == lnk.CommandArgument;
                        } );
                        // if the column is found in the list
                        if ( i >= 0 )
                        {
                            System.Web.UI.WebControls.Image img = new System.Web.UI.WebControls.Image ();
                            //set the appropriate image
                            img.ImageUrl = "~/images/" + ( sl[i].ColumnSort == SortDirection.Ascending ? "asc" : "desc" ) + ".gif";
                            // add space and the sort image to header
                            if ( sl[i].ColumnName == lnk.CommandArgument )
                            {
                                tc.Controls.Add ( new LiteralControl ( " " ) );
                                tc.Controls.Add ( img );
                            }
                        }
                    }
                }
            }
        }
    }
}
This is all it takes to have an ASP.NET GridView that can be sorted by multiple columns.