Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Aug 28, 2009

ASP.Net Custom Paging Control

I've been playing with GridViews for quite some time & have always wondered if there's a better way of displaying the pager at the bottom, instead of the "1 2 3 ..." that you get by default.

As it worked out, I had the reason today to look more into this for a customer request. I happened to find an article that gave code to do this. It was a decent starting point, but I didn’t like how the records displayed were numbered from 0-(count-1), but it got me going.

Here’s what two options I’m considering using:

This one uses media player type links (i.e. |< << >> >|)
<PagerTemplate>
<asp:LinkButton CommandName="Page" CommandArgument="First" ID="LinkButton1" runat="server" Style="color: white">|&lt;</asp:LinkButton>
<asp:LinkButton CommandName="Page" CommandArgument="Prev" ID="LinkButton2" runat="server" Style="color: white">&lt;&lt;</asp:LinkButton>
[Records <%= (Grid.PageIndex * Grid.PageSize)+1 %> - <%= Grid.PageIndex * Grid.PageSize + Grid.Rows.Count %> (<%= iTotalRecordCount %>)]
<asp:LinkButton CommandName="Page" CommandArgument="Next" ID="LinkButton3" runat="server" Style="color: white">&gt;&gt;</asp:LinkButton>
<asp:LinkButton CommandName="Page" CommandArgument="Last" ID="LinkButton4" runat="server" Style="color: white">&gt;|</asp:LinkButton>
</PagerTemplate>
And this one has words for First/Last as well:
<PagerTemplate>
<asp:LinkButton CommandName="Page" CommandArgument="First" ID="LinkButton1" runat="server" Style="color: white">&lt;&lt; First</asp:LinkButton>
<asp:LinkButton CommandName="Page" CommandArgument="Prev" ID="LinkButton2" runat="server" Style="color: white">&lt; Prev</asp:LinkButton>
[Records <%= (Grid.PageIndex * Grid.PageSize)+1 %> - <%= Grid.PageIndex * Grid.PageSize + Grid.Rows.Count %> (<%= iTotalRecordCount %>)]
<asp:LinkButton CommandName="Page" CommandArgument="Next" ID="LinkButton3" runat="server" Style="color: white">Next &gt;</asp:LinkButton>
<asp:LinkButton CommandName="Page" CommandArgument="Last" ID="LinkButton4" runat="server" Style="color: white">Last &gt;&gt;</asp:LinkButton>
</PagerTemplate>
One caveat, I use a variable iTotalRecordCount that is defined on the code behind:
public int iTotalRecordCount = 0;
And defined in a BindGrid() method I call on button click:
iTotalRecordCount = dataTable.Rows.Count;
Lastly, you need to implement the "OnPageIndexChanging" event:
    protected void Grid_PageIndexChanging( object sender, GridViewPageEventArgs e ) {
Grid.PageIndex = e.NewPageIndex;
BindGrid( );
}
Anyway, I hope someone out there finds this useful. :)

Apr 3, 2009

Nesting a Repeater inside of a GridView that is bound to an Array of Custom Objects

Wow, isn't that title a mouthful! But that's exactly the situation that presented itself to me at work this week. Since it too me way longer than I thought it should to figure out, I figured I'd put my effort in here, just in case it might be able to help someone else out someday (possibly even me).

Here's the results:
#NameEmail Addresses
1Ian CazabatIanCazabat@Example.com
Ian.B.Cazabat@Example.com
IanCaz@Example.com
2Malcolm ReynoldsCptnMal@Example.com
Serenity1@Example.com
3Jonas BlaneSnakeDr@Example.com
303rdLSG@Example.com


So, without any further delay here's the code:
ASPX:
<%@ Page Language="c-sharp" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Nested Sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="gvNestingSample" AutoGenerateColumns="False" runat="server" BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical">
<RowStyle VerticalAlign="Top" BackColor="#EEEEEE" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="EmployeeId" HeaderText="#" />
<asp:BoundField DataField="EmployeeName" HeaderText="Name" />
<asp:TemplateField HeaderText="Email Addresses">
<ItemTemplate>
<asp:Repeater runat="server" ID="rptEmailAddrs" DataSource='<%# DataBinder.Eval( Container.DataItem, "EmailAddresses" ) %>'>
<ItemTemplate>
<a href="mailto:<%# Container.DataItem %>"><%# Container.DataItem %></a><br />
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#CCCCCC" ForeColor="Black" />
<SelectedRowStyle BackColor="#008A8C" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
<HeaderStyle BackColor="#000084" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="#DCDCDC" />
</asp:GridView>
</div>
</form>
</body>
</html>


CodeBehind:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page {
protected void Page_Load( object sender, EventArgs e ) {
UserAccount[ ] aryUserAccounts = new UserAccount[ ] {
new UserAccount( 1, "Ian Cazabat", new string[] {"IanCazabat@Example.com", "Ian.B.Cazabat@Example.com", "IanCaz@Example.com"}),
new UserAccount( 2, "Malcolm Reynolds", new string[] {"CptnMal@Example.com", "Serenity1@Example.com"}),
new UserAccount( 3, "Jonas Blane", new string[] {"SnakeDr@Example.com", "303rdLSG@Example.com"})
};

gvNestingSample.DataSource = aryUserAccounts;
gvNestingSample.DataBind( );
}

public class UserAccount {
private long employeeid;
private string employeename;
private string[ ] emailaddresses;

public long EmployeeId {
get { return employeeid; }
set { employeeid = value; }
}
public string EmployeeName {
get { return employeename; }
set { employeename = value; }
}
public string[ ] EmailAddresses {
get { return emailaddresses; }
set { emailaddresses = value; }
}

public UserAccount( ) {
}

public UserAccount( long lEmployeeId, string strEmployeeName, string[] aryEmails ) {
this.employeeid = lEmployeeId;
this.employeename = strEmployeeName;
this.emailaddresses = aryEmails;
}
}
}

Okay, so there you have a working sample of how to create a GridView with a nested Repeater, that gets it's data from an Array of Custom Objects. Here's a couple points of interest:
  1. In order to bind on the data in the object, they must be created as "fields" using get/set.
  2. To access the array that's part of the object use:
    DataSource='<%# DataBinder.Eval( Container.DataItem, "{Array Property Name}" ) %>'
  3. To display the "data elements" from the array, you use:
    <%# Container.DataItem %>
  4. If the "data elements" in the array are custom objects, then you need to use the following:
    <%# DataBinder.Eval( Container.DataItem, "{Property of Custom Object from Array}" )%>
Okay, so that's about got it, hopefully I've helped someone out & I've likely kept myself from losing too much sleep over this issue again! So, go forth & create! ;)

Jul 10, 2008

Display all the properties in an Object

I've come across this problem before, sometimes when working with classes designed by different groups, other times when I'm being lazy & don't want to look through my code. Either way, it's sometimes handy to be able to iterate through the properties of an object. So, here's a "quickie" to dump the property names/values to an exception.

Definition:
public void showObjProperties( object myObject ) {
System.ComponentModel.PropertyDescriptorCollection objProperties = System.ComponentModel.TypeDescriptor.GetProperties( myObject );
string strTmp = "";
string strType = myObject.GetType( ).ToString( );
for ( int i = 0; i < objProperties.Count; i++ ) {
strTmp += strType + "." + objProperties[i].Name + Environment.NewLine;
//strTmp += strType + "." + objProperties[i].Name + ": " + objProperties[i].GetValue( myObject ).ToString( ) + Environment.NewLine;
}
throw new Exception( "Props: " + Environment.NewLine + strTmp );
}


Calling code:
String[] aryString = new String[] { "test1", "test2", "test3" };
showObjProperties( aryString );


Results:
Props: 
System.String[].Length
System.String[].SyncRoot
System.String[].Rank
System.String[].IsReadOnly
System.String[].IsFixedSize
System.String[].IsSynchronized
System.String[].LongLength

Jul 2, 2008

Comparing Custom Objects in C#

Once again I found myself trying to remember the specifics of how to compare specific attributes of a custom object when doing an Array Sort. The linked MS kb article has the specifics, but I'll copy some of that here, for longevity. ;)
private class sortYearAscendingHelper : IComparer
{
int IComparer.Compare(object a, object b)
{
car c1=(car)a;
car c2=(car)b;
if (c1.year > c2.year)
return 1;
if (c1.year < c2.year)
return -1;
else
return 0;
}
}

The key is you have to return one of three values:
  • -1 if the first object is less than the second
  • 1 if the first object is greater than the second
  • 0 if the values of the two objects are equal
Hope this helps someone,
Ian