Hi  eliaso,
Please refer the below sample.
HTML
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" AllowSorting="true" OnSorting="OnSorting">
    <Columns>
        <asp:BoundField DataField="ContactName" HeaderText="Contact Name" SortExpression="ContactName" />
        <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" SortExpression="Country" />
    </Columns>
</asp:GridView>
<script type="text/javascript">
    var GridId = "<%=GridView1.ClientID %>";
    var ScrollHeight = 300;
    window.onload = function () {
        var grid = document.getElementById(GridId);
        var gridWidth = grid.offsetWidth;
        var gridHeight = grid.offsetHeight;
        var headerCellWidths = new Array();
        for (var i = 0; i < grid.getElementsByTagName("TH").length; i++) {
            headerCellWidths[i] = grid.getElementsByTagName("TH")[i].offsetWidth;
        }
        grid.parentNode.appendChild(document.createElement("div"));
        var parentDiv = grid.parentNode;
        var table = document.createElement("table");
        for (i = 0; i < grid.attributes.length; i++) {
            if (grid.attributes[i].specified && grid.attributes[i].name != "id") {
                table.setAttribute(grid.attributes[i].name, grid.attributes[i].value);
            }
        }
        table.style.cssText = grid.style.cssText;
        table.style.width = gridWidth + "px";
        table.appendChild(document.createElement("tbody"));
        table.getElementsByTagName("tbody")[0].appendChild(grid.getElementsByTagName("TR")[0]);
        var cells = table.getElementsByTagName("TH");
        var gridRow = grid.getElementsByTagName("TR")[0];
        for (var i = 0; i < cells.length; i++) {
            var width;
            if (headerCellWidths[i] > gridRow.getElementsByTagName("TD")[i].offsetWidth) {
                width = headerCellWidths[i];
            }
            else {
                width = gridRow.getElementsByTagName("TD")[i].offsetWidth;
            }
            cells[i].style.width = parseInt(width - 3) + "px";
            gridRow.getElementsByTagName("TD")[i].style.width = parseInt(width - 3) + "px";
        }
        parentDiv.removeChild(grid);
        var dummyHeader = document.createElement("div");
        dummyHeader.appendChild(table);
        parentDiv.appendChild(dummyHeader);
        var scrollableDiv = document.createElement("div");
        if (parseInt(gridHeight) > ScrollHeight) {
            gridWidth = parseInt(gridWidth) + 17;
        }
        scrollableDiv.style.cssText = "overflow:auto;height:" + ScrollHeight + "px;width:" + gridWidth + "px";
        scrollableDiv.appendChild(grid);
        parentDiv.appendChild(scrollableDiv);
    }
</script>
Namespaces
C#
using System.Data;
VB.Net
Imports System.Data
Code
C#
protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        this.BindGrid();
    }
}
protected void OnSorting(object sender, GridViewSortEventArgs e)
{
    this.BindGrid(e.SortExpression);
}
private string SortDirection
{
    get { return ViewState["SortDirection"] != null ? ViewState["SortDirection"].ToString() : "ASC"; }
    set { ViewState["SortDirection"] = value; }
}
private void BindGrid(string sortExpression = null)
{
    DataSet ds = new DataSet();
    ds.ReadXml(Server.MapPath("~/App_Data/Customers.xml"));
    DataTable dt = ds.Tables[0];
    if (sortExpression != null)
    {
        DataView dv = dt.AsDataView();
        this.SortDirection = this.SortDirection == "ASC" ? "DESC" : "ASC";
        dv.Sort = sortExpression + " " + this.SortDirection;
        GridView1.DataSource = dv;
    }
    else
    {
        GridView1.DataSource = dt;
    }
    GridView1.DataBind();
}
VB.Net
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    If Not Me.IsPostBack Then
        Me.BindGrid()
    End If
End Sub
Protected Sub OnSorting(ByVal sender As Object, ByVal e As GridViewSortEventArgs)
    Me.BindGrid(e.SortExpression)
End Sub
Private Property SortDirection As String
    Get
        Return If(ViewState("SortDirection") IsNot Nothing, ViewState("SortDirection").ToString(), "ASC")
    End Get
    Set(ByVal value As String)
        ViewState("SortDirection") = value
    End Set
End Property
Private Sub BindGrid(ByVal Optional sortExpression As String = Nothing)
    Dim ds As DataSet = New DataSet()
    ds.ReadXml(Server.MapPath("~/App_Data/Customers.xml"))
    Dim dt As DataTable = ds.Tables(0)
    If sortExpression IsNot Nothing Then
        Dim dv As DataView = dt.AsDataView()
        Me.SortDirection = If(Me.SortDirection = "ASC", "DESC", "ASC")
        dv.Sort = sortExpression & " " & Me.SortDirection
        GridView1.DataSource = dv
    Else
        GridView1.DataSource = dt
    End If
    GridView1.DataBind()
End Sub
Screenshot
