Quang Hung 的个人资料Quang Hung's space照片日志网络更多 工具 帮助

日志


10月26日

asp.net

Introduction

Themes are used to define visual styles for web pages. Themes are made up of a set of elements: skins, Cascading Style Sheets (CSS), images, and other resources. Themes can be applied at the application, page, or server control level. We can create theme by adding App_Themes folder in our project in solution explorer panel. The simple steps are Right click on project and select Add ASP.NET folder – Theme. We can add files into it also. The sample code snippets in this article have been written in C#.

Applying Themes

Applying Theme to a Page

A Theme is an attribute of the page class that we can set in various ways. Once the Theme is set, the page ensures that all of its controls will render according to the visual settings defined in the Theme. Listing 1 illustrates how to define a Theme to a page.

Listing 1

<% Page Language=“C#” Theme=”myTheme” %>

Applying Theme to an Entire Application

In addition to applying an ASP.NET 2.0 theme to our ASP.NET pages using the Theme attribute within the page directive, we can also apply it at an application level from the Web.config file. Then the Theme will be applied automatically to each and every page within the application. This is illustrated in Listing 2.

Listing 2

<configuration>
  <system.web>
    <pages theme=”myTheme”/>
  </system.web>
</configuration>

Applying Theme to all Applications in a Server

If we want to use a particular theme for all the web applications in the server, we can do the same. We can specify the theme that we want to use within the machine.config file. This is illustrated in Listing 3.

Listing 3

<pages buffer="true" enableSessionState="true"
       enableViewState="true" enableViewStateMac="true"
       autoEventWireup="true" validateRequest="true"
       enablePersonalization="false" theme=" myTheme " >
</pages>

Thus adding the Theme attribute to the pages node within the machine.config file is a great solution for the server having multiple applications using the same Theme. Setting a Theme in the machine.config file means that we do not need to use this theme separately for all the applications on the server. If we specify another Theme in the application's web.config file or in the Web page's Page directive, then settings that are set in the web.config file override settings that are in the machine.config file and settings that are placed in the Page directive override both settings in the machine.config and in the web.config files.

Removing Themes

Removing Theme from Server Control

Whether themes are set at application level or page level, we can set a control’s own style on it.

Listing 4

<asp:Textbox ID=”txtTest” Runat=”server”
BackColor=”White” ForeColor=”Black” EnableTheming=”false” />

If we apply myTheme at application or page level, the same theme will be applied in all controls except the "txtTest" textbox control as mentioned above. Instead, the backcolor and forecolor, as mentioned in the code snippet, will be applied.

Removing Theme from Web Pages

If we set the Theme for an entire application in the web.config file and then want to exclude a single ASP.NET page, we can do the same by removing Theme setting at the page level, just like server control. This is illustrated in Listing 5.

Listing 5

<% Page Language=“C#” EnableTheming=”false” %>

If we make EnableTheming attribute false in the page directive, the Theme defined in web.config file will not be applied in the page. But we can still provide Theme in respect of a specific server control in the same page. This is illustrated in Listing 6.

Listing 6

<asp:Textbox ID=”txtTest” Runat=”server” EnableTheming=”true” Theme=” myTheme”/>

Theme vs. StylesheetTheme

The Page directive also includes the attribute StylesheetTheme that we can use to apply themes to a page. So, the big question is: If we have a Theme attribute and a Stylesheet attribute for the page directive, what we should use?

Listing 7

<% Page Language=“C#” StylesheetTheme =”myTheme” %>

The StylesheetTheme attribute works the same as the Theme attribute to apply a Theme to a page. The difference is that, when attributes are set locally on the page within a particular server control, the attributes are overridden by the theme when we use the Theme attribute. But if we apply pages’s theme using the StylesheetTheme attribute, the locally set attributes of the server control will not be overridden.

Creating Theme

In order to create Theme for an application, first we need to create a proper folder structure in application. Within the App_Themes folder, we can create an additional Theme Folder for each and every Theme that we might use in application. The reasons to use more than one Theme are because seasons change, day/night changes, different business units, category of user, user preferences, etc.

The elements of a Theme Folder can be as follows:

·         A Single skin file

·         CSS files

·         Images

Creating a Skin

A skin enables us to modify any of the properties applied to the server controls in our ASP.NET page. Skins can work in conjunction with CSS files or images. To create a Theme we can use a single skin file in the Theme Folder. The skin file extension should be always .skin.  

Listing 8

<asp:Label Runat=”server” ForeColor=”Red” Font-Names=”Verdana” Font-Size=”X-Small”/>
<asp:Textbox Runat=”server” ForeColor=”Red”
Font-Names=”Verdana” Font-Size=”X-Small”  BorderStyle=”Solid” BorderWidth=”1px”
BorderColor=”Yellow” 
Font-Bold=”True” />

As the above example suggest, we need to define a definition for style in respect of each server control in skin file in the application. We can create different skin files in different Theme Folder.

Listing 9

<% Page Language=“C#” Theme =”myTheme” %>

Including CSS Files in Theme

We can provide styles only for server controls using skin file. But ASP.NET pages are made up of HTML controls, raw HTML or raw Text and to implement style for them we need CSS files within Theme Folder. To create a CSS file for Theme we will click Theme Folder and then select Add New Item. In the list of options we should choose the option Style Sheet and will provide a name say test.CSS. When we are using both skin and CSS file, the skin file will take precedence over CSS file for server controls.

Defining Multiple Skin Options

In .skin file of Theme’s Folder we can create multiple definitions in respect of same server control. To create multiple definitions of a single element we can use the SkinID attribute to differentiate among the definitions. The value of SkinID can be anything.

Listing 10

<asp:Textbox Runat=”server” ForeColor=”Blue”
Font-Names=”Verdana” Font-Size=”X-Small”  BorderStyle=”Solid” BorderWidth=”1px”
BorderColor=”Red” 
Font-Bold=”True” />
 
<asp:Textbox Runat=”server” ForeColor=”Red”
Font-Names=”Verdana” Font-Size=”X-Small”  BorderStyle=”Dotted”
BorderWidth=”5px” BorderColor=”Blue” 
Font-Bold=”False” SkinID=”txtDotted”/>
 
<asp:Textbox Runat=”server”
ForeColor=”Yellow” Font-Names=”Arial” Font-Size=”X-Large”  BorderStyle=”Dashed”
BorderWidth=”1px” BorderColor=”Red” 
Font-Bold=”False”  SkinID=”txtDashed”/>

In the above code there is no SkinID for the 1st TextBox server control definition that means it will be used as the default style for TextBox Server control. Where SkinID will be used, the particular definition of TextBox Server Control will be used.

Listing 11

<% Page Language=“C#” Theme =”myTheme” %>
<html>
<body>
<form id=”frmThemeTest” runat=”server”>
<p>
<asp:TextBox ID=”txtThemeTest1”
Runat=”server”>TextBox1</asp:TextBox>
<p>
<asp:TextBox ID=”txtThemeTest2”
Runat=”server” SkinID=” txtDotted “> TextBox1</asp:TextBox>
<p>
<asp:TextBox ID=”txtThemeTest3”
Runat=”server” SkinID=” txtDashed”> TextBox1</asp:TextBox>
</body>
</html>

Working with Themes Programmatically

In the above code the Theme has been defined at design time, but we can work with the Theme programmatically.

Assigning the Pages’s Theme Programmatically

In Listing 12 it is illustrated how we can assign the pages' theme programmatically.

Listing 12

<script runat =”server”>
Protected void Page_PreInit(object sender,
System.EventArgs e)
{
Page.Theme=Request.QueryString[“AppliedTheme”];
}
</script>

Assigning a Control’s SkinID Programmatically

There is another option to assign a specific server control’s SkinID property programmatically, which is illustrated in Listing 13.

Listing 13

<script runat =”server”>
Protected void Page_PreInit(object sender,
System.EventArgs e)
{
txtThemeTest.SkinID=”txtDashed”;
}
</script>

Images in Theme

Themes enable us to incorporate actual images into the style definitions. A lot of controls use images to create a better visual appearance. We should create an Images folder within the Themes folder itself.

Listing 14

<asp:image ID="Image1" 
runat="server" Imageurl="Images/testImage.jpg" />

When the above reaches the client, the browser will be smart enough to request testImage.jpg from the App_Themes/ myTheme /Images directory (when myTheme is the selected theme).

References

Conclusion

Themes are a powerful addition to the ASP.NET framework. By taking advantage of themes, we can dramatically reduce the amount of content that we need to add to individual ASP.NET pages. Themes enable us to define the appearance of a control once and apply the appearance throughout a Web application. Therefore, themes enable us to easily create Web sites that have a consistent and maintainable design.  This improves the maintainability of our site and avoids unnecessary duplication of code for shared styles.

10月17日

C# repeat Repeater

If you can get your recordset into a list you can use LINQ like so:

HTML
<asp:ListView ID="ListView1" runat="server">
        
<LayoutTemplate>
               
<asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
        
</LayoutTemplate>
        
<ItemTemplate>
               
<table>
                    
<tr>
                        
<td><%#Eval("Key")%></td>
                    
</tr> 
                     
<tr>
                        
<td>
                            
<ol>
                               
<asp:ListView ID="ListView2" runat="server" DataSource='<%# Eval("emps") %>' >
                                     
<LayoutTemplate>
                                           
<asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
                                     
</LayoutTemplate>
                                     
<ItemTemplate>
                                            
<li><%#Eval("Name")%></li>
                                     
</ItemTemplate>
                               
</asp:ListView>
                           
</ol>
                       
</td>
                   
</tr>
              
</table>
              
<hr />
         
</ItemTemplate>
</asp:ListView>

Code Behind
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

         
Dim empsByLocation = _
                 
From em In Employee.getEmployees() _
                 
Group em By Key = em.Location Into Group _
                 
Select New With {.Key = Key, .emps = Group}          ListView1.DataSource = empsByLocation
          ListView1.DataBind()
End Sub

My Employee Class
Public Class Employee

     
Public _Location As String
      
Public _Name As String
     
Public _Phone As String
     
Public _ID As Long

 

      Public Sub New(ByVal ID As Long, ByVal Name As String, ByVal Phone As String, ByVal Location As String)
          
Me._Location = Location
          
Me._Name = Name
          
Me._Phone = Phone
           
Me._ID = ID
     
End Sub

      Public ReadOnly Property Name() As String
         
Get
              
Return _Name
         
End Get
     
End Property      Public ReadOnly Property Location() As String
        
Get
             
Return _Location
         
End Get
     
End Property

      Public Shared Function getEmployees() As List(Of Employee)
 
           
Dim employees As New List(Of Employee)
 
            employees.Add(
New Employee(1, "Bob", "09809809", "California"))
            employees.Add(
New Employee(2, "Jack", "3453465", "California"))
            employees.Add(
New Employee(3, "Arnold", "7899878978", "California"))
            employees.Add(
New Employee(4, "Barry", "2134678", "Arizona"))
            employees.Add(
New Employee(5, "Titch", "454458", "Arizona"))
            employees.Add(
New Employee(6, "Mick", "23432424", "Arizona"))

           
Return employees
     
End Function End Class

Will produce the output:

California
  1. Bob
  2. Jack
  3. Arnold

Arizona
  1. Barry
  2. Titch
  3. Mick



You can tidy it up but I hope this was what you were after.

C# Reoeat Repeater

Imagine that you have a database table named Players with a list of basketball players from the NBA. The schema for this table might look as follows:

Players
FullNamevarchar(50)
Teamvarchar(20)

&nbsp;

Improving the Data Model...
The schema for the Players table is extremely simple and far from ideal. If this were a "real" database application, we'd likely have a plethora of additional attributes for a player. Also, we'd likely want a PlayerID primary key field to uniquely identify each player (since a player's name is not a guarantee unique attribute). Furthermore, we'd likely have a separate table to store information about each NBA team, and then have the Team attribute in the Players table be a foreign key.

Given this table schema, imagine that we have the following records:

  • Shaq, Lakers
  • Rick Fox, Lakers
  • Vlade Divac, Kings
  • Tim Duncan, Spurs
  • Kobe Bryan, Lakers
  • Terry Parker, Spurs
  • Robert Horry, Lakers
  • Chris Webber, Kings
  • Mike Bibby, Kings
  • David Robinson, Spurs
  • Doug Christie, Kings

Now, imagine that you wanted to display the NBA players such that the players for each team were grouped together. Clearly, a simple SQL query with an appropriate ORDER BY clause will get all of the players ordered by team. That is, the following query:


SELECT FullName, Team
FROM Players
ORDER BY Team

Will return all the players playing for the Kings, followed by all the players playing for the Lakers, followed by all the players playing for the Spurs. Specifically, the results of the above SQL query, when run on the sample data, will be as follows:

  • Vlade Divac, Kings
  • Chris Webber, Kings
  • Mike Bibby, Kings
  • Doug Christie, Kings
  • Shaq, Lakers
  • Rick Fox, Lakers
  • Kobe Bryan, Lakers
  • Robert Horry, Lakers
  • Tim Duncan, Spurs
  • Terry Parker, Spurs
  • David Robinson, Spurs

Therefore, we could have a DataGrid display the name of each player, followed by their team name. However, what if we wanted the display to be a bit different. Rather than blandly list each player and his associated team, we want to list, in big bold letters, the name of the team, followed by all of its players. That is, we want the results to look something like:


Kings
Vlade Divac
Chris Webber
Mike Bibby
Doug Christie

Lakers
Shaq
Rick Fox
Kobe Bryant
Robert Horry

Spurs
Tim Duncan
Terry Parker
David Robinson

Can we get a DataGrid to render this "style" of output? Sure, if we use a TemplateColumn and a bit of clever programming. We could also obtain such an appearance through the use of a master/detail-type DataGrid, which is discussed in detail in An Extensive Examination of the DataGrid Web Control: Part 14.

In using template, we can implement this sort of display through the use of a DataList and a custom function as well. For this FAQ, let's use the DataList approach.

DataGrid or DataList?
Note that a DataList probably makes more sense here since it is designed for templated columns. Furthermore, the DataList allows for repeated columns via its RepeatColumns property, meaning you could display the teams n to a table column. However, if you need functionality like pagination, then the DataGrid would be a better choice.

Using a DataList to Display the Players, Grouped By Team
Imagine, for a moment, that we only want to display the players for each team, and we're not yet worried about displaying the team name before the list of players. To accomplish this, we could use the following simple DataList:


&lt;asp:DataList runat="server" id="dlPlayers"&gt;
&lt;ItemTemplate&gt;
Container.DataItem("FullName")
&lt;/ItemTemplate&gt;
&lt;/asp:DataList&gt;

This DataList will display a table row and column for each player. Now, to display the team name, we need to be able to determine when the team name switches from one team to the next. That is, when we first start by displaying the players for the Kings, we want to emit the team name Kings and then the player's name, but then for each of the remaining players who play for the Kings, we only want to emit their name. When the first player for the next team (the Lakers) is displayed, again, we want to display both the team name and the player's name; however, for the remaining Lakers players we only want to display the player's name.

In the FAQ, Customizing the Appearance of a DataGrid Column Value, we saw how to use a custom function to output a custom value based on the value of a DataSource field. We'll use this technique in this exercise to emit the player's team name if the team name has switched from a previous value to a new value. This can be accomplished with the following code:


&lt;script runat="server" language="VB"&gt;
...

Function DisplayTeamIfNeeded(team as String) as String
Dim output as String = String.Empty

'Determine if this team has yet to be displayed
If team &lt;&gt; lastUsedTeam then
'Set that the lastUsedTeam is the current team value
lastUsedTeam = team

'Display the team name
output = "&lt;br /&gt;&lt;b&gt;" &amp;amp; team &amp;amp; "&lt;/b&gt;&lt;br /&gt;"
End If

Return output
End Function
&lt;/script&gt;

&lt;asp:DataList runat="server" id="dlPlayers"&gt;
&lt;ItemTemplate&gt;
&lt;%# DisplayTeamIfNeeded(Container.DataItem("Team")) %&gt;
&lt;%# Container.DataItem("Player") %&gt;
&lt;/ItemTemplate&gt;
&lt;/asp:DataList&gt;
VB.NET

 


&lt;script runat="server" language="C#"&gt;
&lt;script runat="server" language="C#"&gt;
...
string lastUsedTeam = String.Empty;

string DisplayTeamIfNeeded(string team)
{
string output = String.Empty;

// Determine if this team has yet to be displayed
if (team != lastUsedTeam)
{
// Set that the lastUsedTeam is the current team value
lastUsedTeam = team;

// Display the team name
output = "&lt;br /&gt;&lt;b&gt;" + team + "&lt;/b&gt;&lt;br /&gt;";
}

return output;
}
&lt;/script&gt;

&lt;asp:DataList runat="server" id="dlPlayers"&gt;
&lt;ItemTemplate&gt;
&lt;%# DisplayTeamIfNeeded((string) DataBinder.Eval(Container.DataItem, "Team")) %&gt;
&lt;%# DataBinder.Eval(Container.DataItem, "Player") %&gt;
&lt;/ItemTemplate&gt;
&lt;/asp:DataList&gt;
C#

C# repeat repeater

The two key templates are the LayoutTemplate and ItemTemplate. The LayoutTemplate specifies the ListView's encasing markup, while the ItemTemplate specifies the markup used to generate each record bound to the ListView. For example, to display an ordered list of items with a ListView, the resulting templates would look like the following:

<asp:ListView ID="..." runat="server" DataSourceID="...">
   <LayoutTemplate>
      <ol>
         <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
      </ol>
   </LayoutTemplate>

   <ItemTemplate>
      <li><%# Eval("columnName") %></li>
   </ItemTemplate>
</asp:ListView>

Since the ListView's LayoutTemplate and ItemTemplate are each defined separately, we need some way to tell the LayoutTemplate, "Hey, for each record you are displaying, put the rendered item markup here." This is accomplished by adding a server-side control with the ID value specified by the ListView's ItemPlaceholderID property. This property defaults to a value of "itemPlaceholder", which is why I have named the PlaceHolder control in the LayoutTemplate as such. I could, however, had given the PlaceHolder control an alternate ID, but then I'd need to specify this value in the ListView's ItemPlaceholdID property.

To output a particular field value in the ItemTemplate, use the databinding syntax, <%# Eval("columnName") %>.

Imagine that the above ListView is bound to an employees database table, and that in the ItemTemplate we were rendering the FullName column within the <li> element. What would the ListView's rendered markup look like?

Well, the ListView would start by rendering it's LayoutTemplate:

<ol>
  <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
</ol>

It would then render its ItemTemplate for each record bound to the ListView control. This might result in the following markup:

<li>Scott Mitchell</li>
<li>Sam Smith</li>
<li>Jisun Lee</li>
<li>Andrew Fuller</li>
<li>Edgar Johnson</li>
<li>Ellen Plank</li>

The ItemTemplate's rendered markup is put in place of the PlaceHolder control (since its ID matches the ListView's ItemPlaceholderID value. The net result is the following markup:

<ol>
<li>Scott Mitchell</li>
<li>Sam Smith</li>
<li>Jisun Lee</li>
<li>Andrew Fuller</li>
<li>Edgar Johnson</li>
<li>Ellen Plank</li>

</ol>

An Example of Displaying Simple Data with the ListView
An ASP.NET version 3.5 website is available at the end of this article with a demo illustrating the ListView control in action. This demo uses the Microsoft Access Northwind database, which is included in the demo application's App_Data folder. The "Simple Data" demo illustrates how to use the ListView to display records from the Northwind database's Products table. An AccessDataSource control is used to query the Products table and bind the resulting records to the ListView.

In particular, the ListView starts by displaying the title "Product Listing" in an <h3> element. It then lists the products within a <blockquote> element, which has the effect of indenting the output. Each product has its name, category, unit price, and quantity per unit displayed. And each product is separated from one another via a horizontal rule element (<hr>), which is defined in the ItemSeparatorTemplate.

The ListView and AccessDataSource's declarative markup follows:

<asp:ListView ID="ProductList" runat="server" DataSourceID="ProductDataSource">
   <LayoutTemplate>
      <h3>Product Listing</h3>
      <blockquote>
         <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
      </blockquote>
   </LayoutTemplate>

   <ItemSeparatorTemplate>
      <hr />
   </ItemSeparatorTemplate>

   <ItemTemplate>
      <h4><%#Eval("ProductName")%> (<%# Eval("CategoryName") %>)</h4>
      Available at <%#Eval("UnitPrice", "{0:c}")%>,
      with <%#Eval("QuantityPerUnit")%>.
   </ItemTemplate>
</asp:ListView>


<asp:AccessDataSource ID="ProductDataSource" runat="server"
   DataFile="~/App_Data/Northwind.mdb"
   SelectCommand="SELECT [ProductName], [QuantityPerUnit], [UnitPrice], [CategoryName] FROM [Alphabetical List of Products]">
</asp:AccessDataSource>

When this page is visited, the ListView renders into the following HTML:

<h3>Product Listing</h3>
<blockquote>

<h4>Chai (Beverages)</h4>
Available at $18.00,
with 10 boxes x 20 bags.

<hr />

<h4>Chang (Beverages)</h4>
Available at $19.00,
with 24 - 12 oz bottles.

<hr />

<h4>Aniseed Syrup (Condiments)</h4>
Available at $10.00,
with 12 - 550 ml bottles.

<hr />

<h4>Chef Anton's Cajun Seasoning (Condiments)</h4>
Available at $22.00,
with 48 - 6 oz jars.

<hr />

<h4>Grandma's Boysenberry Spread (Condiments)</h4>
Available at $25.00,
with 12 - 8 oz jars.

... Many products have been removed for brevity ...

</blockquote>

Which appears in the visitor's browser like so:

The list of products.

Conclusion
The ListView control, new to ASP.NET 3.5, offers the same rich data features found in the GridView, but allows for a much more flexible rendered output. As we saw in this article, the ListView's rendered output is based on the markup, databinding expressions, and Web controls added to its LayoutTemplate and ItemTemplate. There are a number of other templates available, as well, and we will explore these along with features like sorting, paging, deleting, editing, and inserting in future installments of this article series.

Until then... Happy Programming!

C# Repeat Repeater

Linq over DataTable.Rows

Currently you can't directly use Linq over and DataSet/DataTable/DataRowCollection/etc. class. Trying something like this won't work:

var q = from r in table.Rows select r;

Enabling Linq over the classes mentioned above is under consideration by Microsoft and I don't doubt they will enable them. But if you wish to do it now, here is the simple workaround. Everything you need to do (the Linq requires) is that the class implements IEnumerable<T>. So, I will create a generic class that wraps around any IEnumerable and implements IEnumerable<DataRow>. Here is the code:

// simple wrapper that implements IEnumerable<T>
internal class LinqList<T>: IEnumerable<T>, IEnumerable
{
IEnumerable items;

internal LinqList(IEnumerable items)
{
this.items = items;
}

#region IEnumerable<DataRow> Members
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
foreach (T item in items)
yield return item;
}

IEnumerator IEnumerable.GetEnumerator()
{
IEnumerable<T> ie = this;
return ie.GetEnumerator();
}
#endregion
}

The code is pretty straightforward, isn't it. And here is a simple test:

// create and fill table
DataTable table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Rows.Add(new object[]{1});
table.Rows.Add(new object[]{2});
table.Rows.Add(new object[]{3});
// create a wrapper around Rows
LinqList<DataRow> rows = new LinqList<DataRow>(table.Rows);
// do a simple select
IEnumerable<DataRow> selectedRows = from r in rows
where (int)r["Id"] == 2
select r;
// output result
foreach (DataRow row in selectedRows)
Console.WriteLine(row["Id"]);

It is not pretty as it could be but it certainly works. And if you want you can create your own strong typed table implementation that exposes LinqList<DataRow> Rows property. Perhaps using a code generator such as CodeSmith instead of doing boring work yourself.

Published 15. januar 2006 23:25 by Miha Markic
Filed under:

Comments

# re: Linq over DataTable.Rows

30. januar 2006 14:36 by Sahil Malik
I like that "LinqList" :)

# re: Linq over DataTable.Rows (Error FrameW 2.0)

3. februar 2006 8:38 by Dln
The non-generic type 'System.Collections.IEnumerable' cannot be used with type arguments


on word -'IEnumerable<t>' ???</t>

# re: Linq over DataTable.Rows

4. februar 2006 0:46 by Miha Markic
Hi Din,

Did you include System.Collections.Generic namespace? Anyway, check out Sahil's solution, too.