How to format and modify value in data grid row at run time based on previous row values

by Viper 7. July 2009 14:35
grid view row formatting

Download Sample Project

This was a question was asked by one of my site visitors, Mike. Following is the text of the question:

This is a similar question to one you have already answered in formatting Grid Views. However there are 2 main differences. First: I want to change the value of a column (not the format) in any row if the row preceding it has a certain value in the same column.

This question translates to How do you change value of a data grid column based on values of previous row(s). I generalized this question to cover all previous rows and not just the preceding row. Answer to all such questions relies on handling events like RowDataBound or RowCreated events. When a data grid or grid view renders, RowDataBound fires when row is being data bound and then RowCreated is fired after it has been data bound and row has been created. So depending on at what stage of rendering you want to change behavior of a row, you will subscribe either of these events. In the sample project, I am subscribing to RowDataBound event.

Next step is to access values from previous rows. Here you have choice. One, you can keep some local vaiable that stores values from previous row(s) and then use them in current row event handling. Two, you can access the previous GridRow based on index. In this sample i will discuss the approach of accessing previous row based on index and then extracting values from certain cells.

In RowDataBound event handler, GridViewRowEventArgs provides you access to DataItem associated with current row only. You do not have access to DataItem associated with previous rows. But at this point, previous rows have been prepared for rendering. You have access to all the cell values associated with previous row. You can access GridRow object of previous rows and extract text from cells that you are interested in. In the sample project, I am accessing ListPrice from fourth column and then displaying it in current row along with price associated with current row. Well, this does not sound like something that is very interesting or useful. But it serves the purpose of demonstrating you will accomplish the task.

Here is the code snippet from sample project.


protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
 if (e.Row.RowType == DataControlRowType.DataRow)
 {
  double price = -1.0;
  double prevPrice = -1.0 ;
  // Access the previous row.
  if (e.Row.RowIndex != 0)
  {
   GridViewRow prevRow = this.productsGrid.Rows[e.Row.RowIndex - 1];
   if (null != prevRow && 
    prevRow.RowType == DataControlRowType.DataRow)
   {
    double.TryParse(prevRow.Cells[3].Text, out prevPrice);
   }
  }
  var thisRowData = e.Row.DataItem as DataRowView;
  if (!Convert.IsDBNull(thisRowData["ListPrice"]))
  {
   double.TryParse(thisRowData["ListPrice"].ToString(), out price);
  }
  var ctrl = e.Row.FindControl("prevPriceLabel") as Label;
  if (null != ctrl)
  {
   ctrl.Text = string.Format("{0} - {1}", prevPrice, price);
  }
 }
}

The attached sample project is a VS2010 project. There is no VS2010 or .Net4.0 implementation in the project. So if you are using VS2008 or prior, you should be able to copy the implementation files into your own project.

Feel free to send me any request for any other grid view implementation you would like to be answered or implemented.

Views: 1081

Tags: , ,

.Net | ASP.Net | C# | DataGrid

How to download image from a web site programatically using HttpWebRequest

by Viper 16. June 2009 19:15

I am working on adding new features to Marketweet - Twitter Autofollow application. The new feature will show some details about followers of an account. And one of the details is showing image associated with user's profile. To get that to work, I have developed an image service that downloads the user images in the background. This is done using HttpWebRequest object to send request to image URL that is set as user's profile image. Following code shows you how you can download an image from a web site programatically using HttpWebRequest. Also notice how ContentType property of HttpWebResponse is utilized to make sure that response from the specified URL is of type type/xxxx.


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace ConsoleApplication1
{
 class Program
 {
  static void Main(string[] args)
  {
   DownloadImage(113467, 
   @"http://s3.amazonaws.com/twitter_production/profile_images/214863919/logo_normal.jpg");
  }
  static void DownloadImage(int userId, string url)
  {
   HttpWebRequest webRequest = HttpWebRequest.Create(url) as HttpWebRequest;
   HttpWebResponse resp = webRequest.GetResponse() as HttpWebResponse;
   if(resp.StatusCode == HttpStatusCode.OK)
   {
    if (resp.ContentType.Contains("image/"))
    {
     int idx = resp.ContentType.IndexOf("/");
     string fileName = string.Format("{0}.{1}", 
        userId, resp.ContentType.Substring(idx + 1));
     byte[] imageContent = ProcessImageStream(resp);
     FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
     fs.Write(imageContent, 0, imageContent.Length);
     fs.Close();
    }
   }
 }
private static byte[] ProcessImageStream(HttpWebResponse resp)
{
 Int64 iContentLength = resp.ContentLength;
 byte[] streamContent;
 MemoryStream memStream = new MemoryStream();
 const int BUFFER_SIZE = 4096;
 int iRead = 0;
 int idx = 0;
 Int64 iSize = 0;
 memStream.SetLength(BUFFER_SIZE);
 try
 {
  using (memStream)
  {
   while (true)
   {
    iRead = 0;
    byte[] respBuffer = new byte[BUFFER_SIZE];
    iRead = resp.GetResponseStream().Read(respBuffer, 0, BUFFER_SIZE);
    if (iRead == 0)
    {break;}
    iSize += iRead;
    memStream.SetLength(iSize);
    memStream.Write(respBuffer, 0, iRead);
    idx += iRead;
   }
   streamContent = memStream.ToArray();
  }
 }
 catch (Exception ex)
 {
  Console.WriteLine(ex.Message);
  throw;
 }
 return streamContent;
 }
}
}

Discussion

After this entry was posted, Mark pointed out in his comment that it could be achieved in 2 lines of code. I will post those two lines of code here.


Dim r As New System.Net.WebClient  
r.DownloadFile("http://http://aspnetlibrary.com/images/logo.png", 
 "c:\aspnetlibrary.png")

This approach works perfectly fine if both variables in this method signature are very well known. What this means is that you know that target URL is what it says (that I am an image file of type PNG). Here are some issues that you have to think about when you are building a solution that involves downloading of files (image, multimedia or any kind).

  • Lets start with evil that is lurking around these days called Tiny URLs. These started with some good intent but now these have become medium to disguise spam, tricking people into clicking on links that are click advertising, redirecting to questionable sites, key loggers. So if the image URL is like http://tinyurl.com/45fghty, you don't even know what it is. So you really don't know what to save this file as.
  • If you don't know what mime type actually is associated with file that is being downloaded.

What you have to rely on is headers that are associated with response. You can see from code snippet how header information is utilized to establish file type and create file name on the fly.

Views: 1679

Tags:

.Net | C#

How to round off number to 0 or next 0.5

by Viper 12. June 2009 08:31

While working on a clock synchronization service, I had to dig up an old piece of code that I used to round off numbers. For this application I need to round the number to 0 or next 0.5 depending on it proximity to edge. For example if number is 8.001, it gets rounded off to 8.0 and if it is 8.6123 it will be rounded to 8.5. You can argue why not 9 instead of 8.5. Well the logic of the application demands that number is to be rounded down. Here is simple piece of code that will do the trick.


double roundDownNumber = Math.Round(actualNumber * 2.0, 0) / 2.0;

Just simple idea that multiply the number by 2 and round it to ZERO decimal places and then divide by 2.

Views: 521

Tags: , ,

.Net | C#

How to group records using LINQ

by Viper 9. June 2009 04:58

While developing Twitter applications, one of the common patterns that used to emerge is that some particular users will post lot of messages in a short time span. And when searching records, I used to end up with multiple messages from one particular user. So for some user interface, I always had to group messages by user posting the message.

Following code shows how easy it is to group records using LINQ. Just to explain the code a little bit, when search is performed for a certain query term using twitter rest api with Tweetsharp, results are returned as list of TwitterSearchStatus objects. The user who posted the message is indicated by FromScreenName property. So this property becomes the key on which grouping is to be performed. Following group statement shows how grouping is done in LINQ statement.

 var resultsGrpByUser = from searchResult in searchResults
   group searchResult by searchResult.FromUserScreenName
   into userMessages
 select new { FromUser = userMessages.Key, Messages = userMessages };

Above code uses group statement to create group on user name, and the grouping results are returned as Dictionary of anonymous objects that have properties named FromUser and Messages. Following code snippet shows the whole implementation of grouping using LINQ.


static Dictionary<string, List<TwitterSearchStatus>> GetPopularTweets()
{
 List<TwitterSearchTrend> trends = GetDailyTrends();
 if (null == trends ||
     trends.Count == 0)
 {
  return null;
 }
 // For now only process first trend term.
 List<TwitterSearchStatus> searchResults = SearchForTerm(trends[0].Query);
 if (searchResults.Count == 0)
 {
  return null;
 }
 var resultsGrpByUser = from searchResult in searchResults
   group searchResult by searchResult.FromUserScreenName
   into userMessages
 select new { FromUser = userMessages.Key, Messages = userMessages };
 Dictionary<string, List<TwitterSearchStatus>> dict = 
  new Dictionary<string, List<TwitterSearchStatus>>();
 foreach(var userMessage in resultsGrpByUser)
 {
  Console.WriteLine(userMessage.FromUser);
  foreach(var twitterStatus in userMessage.Messages)
  {
   Console.WriteLine("\t{0}", twitterStatus.Text);
  }
  dict[userMessage.FromUser] = userMessage.Messages.ToList();
  Console.WriteLine("*************");
 }
 return dict;
}

Views: 797

Tags:

.Net | C# | LINQ

How to verify twitter login credentials

by Viper 5. June 2009 04:53

As more and more have started to integrate Twitter API into the applications and allowing user to post messages and do other twitter related tasks, one of the essential step in the work flow is to verify a user's twitter credentials. There are certain tasks you can perform without logging into API. But when it comes to posting messages or pulling a user's data etc., Twitter API wants the user to be authenticated. Here is a code snippet that shows how you can use Twitter API to verify a user's credentials or verify user's login information.


static TwitterUser VerifyTwitterCredentials(string login, string password)
{
 IFluentTwitter ft = FluentTwitter.CreateRequest();
 ft.AuthenticateAs(login, password);
 ft.Accounts().VerifyCredentials().AsJson();
 var resp = ft.Request();
 TwitterUser tUser = resp.AsUser();
 if (null == tUser)
 {
  var err = resp.AsError();
  Console.WriteLine("Twiiter Error: " + err.ErrorMessage);
 }
 return tUser;
}

When verification fails, you will get a response that will not get converted to TwitterUser object and method will return null object.

Views: 1948

Tags: ,

.Net | C# | VB.Net

WinForms Samples, Tutorials, Demos, Articles and more

by Viper 16. April 2009 19:14

Read, download samples, tutorials etc. for WinForms.

Views: 786

Tags:

.Net | C# | VB.Net | WinForms

ID3V2 Detect and Manipulate MP3 file format using C# with Idsharp Library

by Viper 21. March 2009 18:18

Long time ago I wrote an article Detect file type or mime type based on content. If you look at the XML file that contained magic signature of different file types, one of the type was MP3 files. And magic signature for MP3 files is that first 3 bytes of file content are ID3. The format of MP3 files is very well defined and explained at ID3.org. Although it is very well defined but it is not something very straight forward and not a job for faint heart to understand it.

For one of new development adventure I am tasked with digging little bit deep into file structure of MP3 files and find out some meta data. Things like Artist Name, Title, Track Number, Year Of Release etc. So I looked around the site and found reference to IDSharp library developed for .Net and is COM visible as well. So you can use it in any application that can invoke COM interfaces. The library is available on sourceforge. But there is no source code for the actual core library. It is only available as .Net assembly. I really needed source code for it because I was curious about implementation and I had to make some modifications as well for the kind of work I was doing.

So I fired up good old tool Reflector and dis-assembled the assembly to generate the source code for it. I had to fix few compile errors after disassembly. But finally I made it to work as expected. So I thought I will share the source code of IdSharp library with people who are interested in it.

Download Source Code For IdSharp Library

From the following code snippet you can see how you can load a MP3 file to get all information about the file. And then you can actually change ID3 tag information as well and save the file with new information. In the sample code, I changed the name of the artist as well as album name. You can see from the screen shot that it did work.

static void Main(string[] args)
{
var id3v2 = ID3v2Helper.CreateID3v2("Hello.mp3");
Console.WriteLine("Artist: {0}", id3v2.Artist);
Console.WriteLine("Title: {0}", id3v2.Title);
Console.WriteLine("Album: {0}", id3v2.Album);
Console.WriteLine("Genre: {0}", id3v2.Genre);
Console.WriteLine("Year: {0}", id3v2.Year);
Console.WriteLine("TrackNumber: {0}", id3v2.TrackNumber);
Console.WriteLine("Media Type: {0}", id3v2.MediaType);
Console.WriteLine("CD Identifier: {0}", id3v2.MusicCDIdentifier.TOC);
id3v2.Artist = "Byteblocks.com";
id3v2.Title = "ID3v2 Song";
id3v2.Save("Bytes.mp3");
}

Views: 4818

Tags: , , ,

.Net | C# | Mime Type | File Format

Manipulating Bits and Bytes Using C#

by Viper 21. March 2009 05:45

Recently I was working on detection of MP3 file format when a user uploads a file to a web site. Part of the detection was to look for ID3 header and figuring out what flags were set in header. The format specification tells you at what bit locations to check for what flags. This meant that you will need some mechanism to figure out what bits are set with in a byte. If you are seasoned C/C++ developer, you pretty much know that this meant that doing some low level bit shift operations on that byte to rotate through them to check which bit is set and which is not set. So if you will write that code in C#, it will look like snippet below.


static void ConvertToBinaryFormat(byte n)
{
 var flags = new BitArray(8);
 var counter = 8;
 var idx = 0;
 while(counter > 0)
 {
  flags.Set(idx++, ((n & 1) == 1));
  n >>= 1;
  counter--;
 }
 PrintBitArray(flags);
}

static void PrintBitArray(BitArray ba)
{
 Console.WriteLine();
 for(int i = ba.Length-1; i >= 0; i--)
 {
 Console.Write("{0}", ba[i] ? 1 : 0);
 }
}

Looking at the code, you are already saying that I have already used BitArray class object in this function. Then why am I doing all the low level operations. I intentionally introduced BitArray here to demonstrate that you really do not need to do all the low level operations to check what bits are set. BitArray class already does that for you. Following one line of code does the same thing that I did by doing some bit shifting.


var newFlags = new BitArray(new byte[] {20});
PrintBitArray(newFlags);

If you look at PrintBitArray method, you will notice that it is using reverse loop to print each bit. When bit shit operation is being done, bit array gets filled from right to left. This means that higher order bits get pushed low. And BitArray class does the same thing. So you will have to access the array from bottom.

Views: 2148

Tags: ,

.Net | C#

Powered by BlogEngine.NET 1.4.6.1
Theme by Naveen Kohli

Recent

By Categories