Jon's Blog

.NET Development & More

Removing Control From Tab Order

This one is simple but nice to know.  To remove a control from the tab order you can just set its TabIndex to -1.  I thought there might be a "turn tabbing off" property, but this seems to be the easiest way.

<asp:CheckBox ID="myCB" runat="server" Text="MyCB" TabIndex="-1" />

LinqDataSource: Efficient Custom Paging with LINQ

NOTE: If you set your LinqDataSource's AutoPage property to true and are using SQL Server (2005+ I believe) then it will automatically use Skip() and Take() as seen below. However, if you want to do it manually or wonder how it works then read on.

Creating a GridView (or other data control) with efficient paging is very easy with LINQ.  You can thank the Take and Skip operators for this; they allow you to only pull back the records you need.  In the simple example below we are using a LinqDataSource and handling its onselecting method to create our LINQ query and do our paging.  Set AutoPage to false since we are writing code to handle paging ourselves.  Also the PageSize property of the GridView control is being populated from a constant in the code-behind class.

ASPX:

<asp:LinqDataSource ID="linqDS" runat="server" AutoPage="false" 
    ContextTypeName="Namespace.MyDataContext" 
    onselecting="linqDS_Selecting" />
        
<asp:GridView ID="myGV" runat="server" DataSourceID="linqDS"
    AllowPaging="true" PageSize="<%# PAGE_SIZE %>"
    AutoGenerateColumns="false">
    <Columns>
        <!--Removed for simplicity -->
    </Columns>
</asp:GridView>

 

Code-behind:

// Const declared at top of code-behind
public const int PAGE_SIZE = 100;

protected void linqDS_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    // LINQ query
    var query = from c in myDC.Class
                select c;

    // Do advanced query logic here (dynamically build WHERE clause, etc.)     
    
    // Set the total count     
    // so GridView knows how many pages to create    
    e.Arguments.TotalRowCount = query.Count();

    // Get only the rows we need for the page requested
    query = query.Skip(myGV.PageIndex * PAGE_SIZE).Take(PAGE_SIZE);

    e.Result = query;
}

 

GridView EmptyDataTemplate: Get Rid of That Annoying Border!

If you are like me then you may have a CSS table style for your GridView with a specific border.  When you use the the EmptyDataTemplate you may then have a border around your message.  I create a CSS class and then use the EmptyDataRowStyle and set its CssClass.  Note, in the GridView I am also setting the default border to 0.  Example:

CSS

table.myGridClass .empty td
{
border-style: none;
border-width: 0px;
background-color: #ffffdd;
}

 

ASPX

<asp:GridView ID="myGridView" runat="server" CssClass="myGridClass" BorderWidth="0">
<HeaderStyle CssClass="myHeaderStyle" />
<RowStyle CssClass="myRowStyle" />
<EmptyDataRowStyle CssClass="empty" />
<EmptyDataTemplate>Your message here.</EmptyDataTemplate>

ASP.NET AJAX Control Toolkit: Bug with Modal Popup Extender

I found a bug in the September 30, 2009 release of the AJAX Control Toolkit.  When you press a button that is inside of a Modal Popup dialog box it will cause a full page postback instead of a partial postback.  When I reverted to the May 13, 2009 release this did not occur.

By the way, I also ran into another weird issue on the September 2009 release where random commas were being inserted into my text box on each postback.  If you are having this issue I also recommend reverting to the May 2009 release.

ASP.NET: Beware of Blank ImageUrl on ImageButton

Earlier today I was debugging a rather tricky issue.  It came down to the fact that an ImageButton control was not getting its ImageUrl property set in certain scenarios.  This would cause ASP.NET to output the following HTML for this control:

<input type="image" name="myName" id="myID" src="" />

 

This was causing the page to request Default.aspx since a src was not explicitly defined*.  So be sure to set the ImageButton control (or its container element) to Visible="false" if you are not setting its ImageURL property.  Otherwise you may have some code-behind logic on Default.aspx executed when you aren't expecting it!

* I assume this is because Default.aspx is set as the default document in IIS.

ASP.NET AJAX: Checking for Partial Postback - IsInAsyncPostBack

My initial thought is always to look for a property on the Page object, but this is actually a property on the ScriptManager.  So if you want to only execute code if it isn't a partial page post back you can do the following:

if (!scriptManagerInstance.IsInAsyncPostBack)
{
    // Do stuff here
}

LINQ Advanced Search

When creating an advanced search you often need to dynamically create the Where statments in your SQL.  Here is an easy way to do this in LINQ.  In the example below orderID, lastName, firstName, shipped are all values retrieved from controls on the page.

var query = from orders in dataContext.MyOrdersTable
select orders;

if (orderID.HasValue)
{
query = query.Where(order => order.OrderID == orderID);
}
if (!string.IsNullOrEmpty(lastName))
{
query = query.Where(order => order.LastName == lastName);
}
if (!string.IsNullOrEmpty(firstName))
{
query = query.Where(order => order.FirstName == firstName);
}
if (shipped.HasValue)
{
query = query.Where(order => order.Shipped == shipped);
}

myGridView.DataSouce = query;
myGridView.DataBind();

Using ASP.NET and GDI+ to Resize Uploaded Image

Below is some sample code I used to resize an uploaded image if the image does not meet the required width and height.  MAX_WIDTH and MAX_HEIGHT below are constants.  Change them as needed.  I am saving the resized image as a JPEG.  It is also a good idea to inform the user that their image was resized.  I removed that code to increase readability.

Note: In this sample the image is being saved to a database, but you could also save it to a file if you wanted to.

if (fileUpload.HasFile)
{
// Get uploaded image from upload control
System.Drawing.Image uploadedImage = System.Drawing.Image.FromStream(fileUpload.PostedFile.InputStream);

// Check width and height of image and resize if necessary
if (uploadedImage.Width > MAX_WIDTH || uploadedImage.Height > MAX_HEIGHT)
{
// Get the factor we must resize by
decimal heightFactor = Decimal.Divide(uploadedImage.Height, MAX_HEIGHT);
decimal widthFactor = Decimal.Divide(uploadedImage.Width, MAX_WIDTH);
decimal resizeFactor = Math.Max(heightFactor, widthFactor);

// Calculate the new height and width using the resize factor
int newHeight = Convert.ToInt32(uploadedImage.Height / resizeFactor);
int newWidth = Convert.ToInt32(uploadedImage.Width / resizeFactor);

Bitmap sourceBitmap = new Bitmap(uploadedImage);
Bitmap newBitmap = new Bitmap(newWidth, newHeight);
Graphics graphics = Graphics.FromImage(newBitmap);
MemoryStream memoryStream = new MemoryStream();

try
{
// Set quality settings and save to MemoryStream object as Jpeg
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, newWidth, newHeight));
newBitmap.Save(memoryStream, ImageFormat.Jpeg);

// Save to Business Object
bizObject.FileData = new Binary(memoryStream.ToArray());
bizObject.FileType = "image/jpeg";
bizObject.FileName = Path.GetFileNameWithoutExtension(fileUpload.FileName) + ".jpg";
}
catch (Exception)
{
throw;
}
finally
{
// Dispose of graphics objects
memoryStream.Dispose();
sourceBitmap.Dispose();
newBitmap.Dispose();
graphics.Dispose();
}
}
else
{
// Image size is correct, so save what was uploaded
bizObject.FileType = fileUpload.PostedFile.ContentType;
bizObject.FileName = fileUpload.FileName;
bizObject.FileData = new Binary(fileUpload.FileBytes);
}

// Other code removed for clarity
}

File Upload: File Extension Validation

This is an easy way to validate the file extension on a FileUpload control.  This way you won't have to postback to the server to validate.  Unless, of course, the user has JavaScript turned off.  The example below is for images (JPEG, GIF, or PNG).

<asp:RegularExpressionValidator ID="regxImage" runat="server" Text="*" 
ErrorMessage
="Image must be a JPEG, GIF, or PNG."
ValidationExpression="(.*?)\.(jpg|JPG|jpeg|JPEG|jpe|JPE|png|PNG|gif|GIF)$"
ControlToValidate="myFileUpload" />

DropDownList: Customized DataTextField

If you try to bind a DropDownList to a DataSouce you will find that you can only use one column as the DataTextField.  The easiest way I have found to overcome this is to manually add the items to the DropDownList like this:

foreach (var item in items)
{
ListItem li = new ListItem(item.FirstName + " " + item.LastName, item.ID);
ddlMyDDL.Items.Add(li);
}

You could also change your query/stored procedure to pull back what you needed displayed in a single column.  But I prefer the above method.