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

日志


12月1日

add style sheet to page

Just add a runat attribute to your traditional link tag. ID attribute has to
be present, and tag has to be properly closed (not like HTML).<head>
<link id="MyStyleSheet" rel="stylesheet" type="text/css" runat="server" />
</head>Then in your Page_Load, simply add a "href" attribute as below:Sub
Page_Load(Sender As Object, E As EventArgs)
If Not (IsPostBack)
MyStyleSheet.Attributes.Add("href","/css/flostyle.css")
End If
End SubHope this helps
--

Bruno Alexandre
(a Portuguese in Københanv, Danmark)


<> escreveu na mensagem
news: oups.com...
I'm afraid I can't use 2.0. Is this not possible in 1.1?

Bruno Alexandre wrote:
11月14日

Convert SQLServer2005 to SQLServer2000

justin
bạn thử cách này xem
1.Tạo database trong sqlserver 2000
2.Genarete script trong sqlserver 2005 (chú ý trước khi gen phải chọn Script for Server Version là SQL Server 2000 để tránh lỗi khi thực thi bên SQLServer 2000)
3.thực thi script đó trong sqlserver 2000 thế thôi

(in reply to 4EVER_IT)
Post #: 2
RE: Convert SQL2005 sang SQL Server 2000 - 9/30/2008 10:35:32 AM   
Không Có Bài Mới
justin
thêm cái này nữa nhưng cố gắng dịch

How to Downgrade a Database from SQL Server 2005 to SQL Server 2000
 
As you may all know, SQL Server 2005 request a minimum of 8GB RAM to work… let say satisfactorily. I first didn’t knew that and after a while from the upgrade I did from SQL Server 2000 to 2005 my SQL Services were starting to crash three or four times per DAY!!!
 
At first I thought I was being attacked, but soon I realized it was nothing like that. I then decided to downgrade to an SQL Server 2000 edition. Though I looked around the internet to find some information on how to do that, I got very disappointed when I realized that no actual documentation of any kind could be found for that. So I am posting this thread to inform you on the procedures I had to follow for this action.
 
Before beginning I must assume, firstly that the user, who will attempt such thing, has  a basic knowledge of SQL Environment, secondly that he has the two versions already installed (both 2000 and 2005), that a basic backup of the databases has been created and finally that all the 2005 SQL Server Users have been created at the SQL Server 2000 environment as well.
 
Step 1 Generating Scripts for the Database Elements and Structures
 
1)      Right-click over the desired Database at 2005, Choose Tasks and the Generate Scripts (Option).
2)      At the pop-up Dialog Box click at the Script All Objects in the selected Databases check box, to activate it and then Click the Next Button.
3)      Set the following Elements to the following Values
a.       Script Collation , set to TRUE
b.      Script Database Create, set to TRUE
c.       Script of SQL Version, set to SQL SERVER 2000
d.      Script foreign keys, set to FALSE
e.       Script Triggers, set to FALSE
 Then Hit the Next button
4)      Select the way the generated scripts should be saved (There are different selections. The most common one is Clipboard). Finally click the Next button till you reach the end.
5)      Click Finish
 
After completing this procedure, we have to move to the SQL SERVER 2000 environment. Here, by using the Query Analyzer, we will have to run the scripts that were generated using the master database. Copy and Paste the script at the Query Analyzer and run it. After that the Structure of the Database will be created.
 
Be careful, the SQL Server 2005 Edition inserts the Views in a random place through the script. Therefore, all the scripts that are referred to the Views MUST be moved to the end of the script. If the Query Analyzer shows some errors do not be bothered. Delete all the elements created from the script and after you fix the code run it again.
 
 
Step2 Moving the data from 2005 to 2000
 
1)      After completing the previous step successfully, moving the data follows. Right-click at the 2005 database you used to run the previous step and select Tasks and then choose the Export Data (option).
2)      From the pop-up Dialog Box, select the Source Db and Click at the Next Button.
3)      At the next step you will have to choose the destination server and the destination Database for the Data to be exported. Then Click Next.
4)      A List of all the Source Database’s Elements will appear in the screen. Select one by one all the Elements you wish to move and for each one click at the button Edit Mappings (Located at the bottom right corner of the Dialog Box just under the Elements list). A new Dialog box will pop-up. Select the Delete rows in Destination Tables option and activate the Enable Identity Insert Option. (Remember to repeat this action for each of the selected Element from the list that will be moved.
 
CAUTION!!! A malfunction of the SQL Server 2005 has been found. Not sure why, after multiple tries I have observed that when I tried to move more than twelve Elements at once, the Export Data Wizard of SQL Server 2005 seemed to disable the Enable Identity Insert Option that was activated over the Edit Mappings Dialog Box. But if the number of the selected Elements is smaller than 12 no problem seemed to appear.
 
Step 3 Generating Scripts for the Database Foreign Keys and Triggers
 
Finally, to successfully finish the downgrade of the Database, the Triggers and the Foreign Keys of the DB must be produced. The procedure that should be followed is the one stated next:
 
1)      Right-Click at the SQL 2005 Database and Select from Tasks Menu the Generate Scripts Option.
2)      Using the pop-up Dialog Box make sure that the check box Script All Objects in the selected Databases is not enabled and hit the Next Button.
3)      Set all the Elements on the List to a False Value except the ones that follow:
a.       Include IF NOT EXISTS , set to TRUE
b.      Script Owner, set to TRUE
c.       Script of SQL Version, set to SQL SERVER 2000
d.      Script foreign keys, set to TRUE
e.       Script Triggers, set to TRUE
 Then Hit the Next button
4)      After finishing reading the Elements of the Database, a new list will appear at the Dialog Box. Make sure that you select ONLY THE TABLES of the Database and hit the Next Button.
5)      At the screen that follows hit the Select All button and the Next.
6)      Select the way the generated scripts should be saved (There are different selections. The most common one is Clipboard). Finally click the Next button till you reach the end.
7)      Click Finish Button.
 
After completing this procedure, we have to move to the SQL SERVER 2000 environment. Here, by using the Query Analyzer, we will have to run the scripts that were generated using the master database. Copy and Paste the script at the Query Analyzer and run it. After that the Foreign Keys and the Triggers of the Database will be created.
 
After these steps the database should be fully functional under the SQL Server 2000 edition.

----------------------------------------------
codePrject

Introduction

Moving databases from SQL Server 2005 to SQL Server 2000 is not impossible and can really be quite easy once you come to grips with the basics. Microsoft has made it very easy to move databases from 2000 to 2005 by using backup and restore built into the admin tools, but this is not backwards compatible and has caused some issues, to say the least. The content of this article owes a lot to the very talented Craig Murphy, who suggested using a publishing wizard for reverting 2005 databases to 2000 in a blog entry.

I am trying to write this for all levels, so please excuse the simplistic nature, as not everyone is as special as you.

SQL Server 2005 Database Publishing Wizard 1.1

The Database public wizard is intended for Developers to create databases with script or management GUIs, develop and change databases and then be able to script the finished database for inclusion to installation routines. This is an installation and separate program from your 2005 Server Management Studio, which can script and publish databases from 2005 to 2005 and well as 2000 databases.

The current download can be found here (this may well change as Microsoft does move and change pages). You need the .NET 2.0 Framework and Microsoft Feature Pack installed, as well. I didn't know if I had the Feature Pack, as I have the SQL 2005 Developer Edition and it installed fine without any Feature Pack.

Download and Install

You should be able to do this without my help.

Running Publishing Wizard for 2005 to 2000ll

Start The Wizard (once you install it, it's also a separate program from SQL Management Studio).

Select a Server and authentication details.

Select a Database.

Select an Export File.

Set Requirements. Note that this extract will do Schema and Data for SQL Server 2000. If you have a large database, this could take a long time and produce a massive file.

Review Summary:

Progress and Results:

With luck, you will see a success. If not, go back and review the selections. I've tried this with various live and not live databases with no issues.

Getting It All Back Into SQL Server 2000

So you now have a SQL file with your schema and data as describe above. If it is fairly small, then you can simply open it in a Query Analyzer (SQL 2000) or a Query Window in 2005 Management Studio and connect to your 2000 database. However, if your database is even slightly complex or you have a fair bit of data, the SQL script file will be too big and it just won't load. So you have to use a command line option. You should be able to do this without my help.

Warning: Running very large SQL scripts could take a while.

SQL 2005 sqlcmd

Below is using my SQL Server 2005 Developer Edition with sqlcmd to execute the file. This works fine with targeted SQL Server 2000 SP4.

Collapse
c:> sqlcmd -E -S my2000server -d mydatabase -i c:\sandbox.sql 
or
c:> sqlcmd -U sa -P password -S my2000server -d mydatabase -i c:\sandbox.sql

SQL 2000 osql

If you really want to use osql on your SQL 2000 box, then this should do it. No prizes for figuring out the command parameters are the same. There might be a performance advantage running it directly on the SQL 2000 box, but I've not looked into this.

Collapse
c:> osql -E -S my2000server -d mydatabase -i c:\sandbox.sql 
or
c:> osql -U sa -P password -S my2000server -d mydatabase -i c:\sandbox.sql

Where -U is sqllogin, -P is password, -E is integrated authentication, -S is server name, -d is database name and -i is the SQL script file you created. If you get stuck with these command items, read the SQL server books online. Oh, please don't post saying I should never use SA for this sort of script; I may already know that.

History

1.0 Initial Release 06/09/2005

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Frank Kerrigan


Frank Kerrigan

Currently developing Insurance systems with SQL Server, ASP.NET, C#, ADO for a company in Glasgow Scotland. Very keen on OOP and NUNIT testing. Been in IT forever (12+ years) in mix of development and supporting applications / servers. Worked for companies big and small and enjoyed both.

Developed in (newest first) : C#, Progress 4GL, ASP.NET, SQL TSQL, HTML, VB.NET, ASP, VB, VBscript, JavaScript, Oracle PSQL, perl, Access v1-2000, sybase/informi, Pic Controllers, 6502 (ask your dad).

MCAD ongoing
MCP C# ASP.NET Web Applications
MCP SQL Server 2000
HND Computing
OND / HNC Electrical Engineering,

11月13日

Change text of Label in Master page at runtime

Try this snippet -

Label lbl = this.Master.Page.FindControl("lblHeader") as Label;
if (lbl != null)
{
lbl.Text = "Welcome from the content page!";
}


It is assumed here that the label ID of your Label server control is
lblHeader
11月11日

Uploading Files in ASP.NET 2.0


  Uploading Files in ASP.NET 2.0

Bill Evjen
Reuters

December 2005

Applies to:

   Microsoft ASP.NET 2.0
   Microsoft Visual Web Developer 2005 Express Edition

Summary: Learn how to use the new FileUpload server control in Microsoft ASP.NET 2.0. (18 printed pages)

Contents

Introduction
An Example of the FileUpload Server Control
Conclusion

Introduction

Ever since Microsoft ASP.NET was introduced with version 1.0, there has been the built-in means of building Web applications that had the ability to upload files to the hosting server. This was done through the use of the File Field HTML server control. I previously wrote an MSDN article on how to effectively use this control in your ASP.NET applications. This article is a reintroduction to the file upload process, but instead of using the File Field control, I will show you how to effectively use the new FileUpload server control that is offered through ASP.NET 2.0.

It is important to note that while this article introduces you to the new FileUpload server control, it is still quite possible to use the File Field control in your applications today.

An Example of the FileUpload Server Control

When using the File Field control in ASP.NET 1.x you had to take a few extra steps to get everything in line and working. For example, you were required to add enctype="multipart/form-data" to the page's <form> element on your own. The new FileUpload server control provided in ASP.NET 2.0 makes the process of uploading files to the hosting server as simple as possible.

In the end, you are trying to allow access to program the HTML <input type="file"> tag. This tag is used to work with file data within an HTML form. In the past when using classic ASP (ASP 3.0 or earlier), many programmers worked with third-party components to upload files from the client to the server. Now, with .NET and this new control, uploading is taken care of for you. Listing 1 shows you how to use the FileUpload control to upload files to the server.

Note   The sample code is provided in both Microsoft Visual Basic and C#.

Listing 1. Uploading files to the server using the FileUpload control

Visual Basic

<%@ Page Language="VB" %>

<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If FileUpload1.HasFile Then
Try
FileUpload1.SaveAs("C:\Uploads\" & _
FileUpload1.FileName)
Label1.Text = "File name: " & _
FileUpload1.PostedFile.FileName & "<br>" & _
"File Size: " & _
FileUpload1.PostedFile.ContentLength & " kb<br>" & _
"Content type: " & _
FileUpload1.PostedFile.ContentType
Catch ex As Exception
Label1.Text = "ERROR: " & ex.Message.ToString()
End Try
Else
Label1.Text = "You have not specified a file."
End If
End Sub
</script>

<html >
<head runat="server">
<title>Upload Files</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:FileUpload ID="FileUpload1" runat="server" /><br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click"
Text="Upload File" />&nbsp;<br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label></div>
</form>
</body>
</html>

C#

<%@ Page Language="C#" %>

<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
try
{
FileUpload1.SaveAs("C:\\Uploads\\" +
FileUpload1.FileName);
Label1.Text = "File name: " +
FileUpload1.PostedFile.FileName + "<br>" +
FileUpload1.PostedFile.ContentLength + " kb<br>" +
"Content type: " +
FileUpload1.PostedFile.ContentType;
}
catch (Exception ex)
{
Label1.Text = "ERROR: " + ex.Message.ToString();
}
else
{
Label1.Text = "You have not specified a file.";
}
}
</script>

<html >
<head runat="server">
<title>Upload Files</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:FileUpload ID="FileUpload1" runat="server" /><br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click"
Text="Upload File" />&nbsp;<br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label></div>
</form>
</body>
</html>

Running this page, you will notice a few things if you look at the source code generated for the page. This source code is presented in Listing 2.

Listing 2. The source code generated from the FileUpload control

<html  >
<head><title>
Upload Files
</title></head>
<body>
<form name="form1" method="post" action="MyFileUpload.aspx"
id="form1" enctype="multipart/form-data">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNDcxNTg5NDg3D2QWAgIEDxYCHgdlbmN0eXBlBRNtdWx0aXBhcnQvZm9yb
S1kYXRhZGQUQEUFMY1+/fp1mnrkbqmVNQIzFA==" />
</div>

<div>
<input type="file" name="FileUpload1" id="FileUpload1" /><br />
<br />
<input type="submit" name="Button1" value="Upload File"
id="Button1" />&nbsp;<br />
<br />
<span id="Label1"></span>
</div>

<div>

<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION"
value="/wEWAgLB+7jIAwKM54rGBv2Iz6LxVY7jWec0gZMxnuaK2ufq" />
</div></form>
</body>
</html>

The first thing to notice is that because the FileUpload control is on the page, ASP.NET 2.0 modified the page's <form> element on your behalf by adding the appropriate enctype attribute. You will also notice that the FileUpload control was converted to an HTML <input type="file"> element.

When the page from Listing 1 is run, you can select a file and upload it to the server by clicking the Upload File button on the page. There are some important items we should go over for this example so you understand all the needed pieces to make this work. For the example in Listing 1 to work, you have to make the destination folder on the server writeable for the account used by ASP.NET so the file can be saved to the specified folder.

If you think your ASP.NET account is not enabled to write to the folder you want, simply open up Microsoft Windows Explorer and navigate to the folder to which you want to add this permission. Right-click on the folder (in this case, the Uploads folder), and then select Properties. In the Properties dialog box, click on the Security tab and make sure the ASP.NET Machine Account is included in the list and has the proper permissions to write to disk (see Figure 1).

Figure 1. Looking at the Security tab of the Uploads folder

If you don't see the ASP.NET Machine Account under the Security tab, you can add it by clicking the Add button and entering ASPNET (without the period) in the text area, as illustrated in Figure 2.

Figure 2. Adding the ASP.NET Machine Account to the folder security definition

Click OK to add the ASP.NET Machine Account to the list. From here, make sure you give this account the proper permissions and then click OK, and you are ready to go.

The Submit button on the page causes the Button1_Click event to occur. This event uploads the file and then displays a message telling you if the upload was successful by posting information about the file uploaded. If it was unsuccessful, the page displays an error message describing why the upload failed.

By using the FileUpload control that converts itself to an <input type="file"> tag, the browser automatically places a Browse button next to the text field on the ASP.NET page. You don't have to program anything else for this to occur. When the end user clicks the Browse button, he can navigate through the local file system to find the file to be uploaded to the server. This is shown in Figure 3. Clicking Open will place that filename and the file's path within the text field.

Figure 3. Choosing a file

Working Around File Size Limitations

You may not realize it, but there is a limit to the size of a file that can be uploaded using this technique. By default, the maximum size of a file to be uploaded to the server using the FileUpload control is around 4MB. You cannot upload anything that is larger than this limit.

One of the great things about .NET, however, is that it usually provides a way around limitations. You can usually change the default settings that are in place. To change this size limit, you make some changes in either the web.config.comments (found in the ASP.NET 2.0 configuration folder at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG) or your application's web.config file.

In the web.config.comments file, find a node called <httpRuntime> that looks like the following:

<httpRuntime 
executionTimeout="110"
maxRequestLength="4096"
requestLengthDiskThreshold="80"
useFullyQualifiedRedirectUrl="false"
minFreeThreads="8"
minLocalRequestFreeThreads="4"
appRequestQueueLimit="5000"
enableKernelOutputCache="true"
enableVersionHeader="true"
requireRootedSaveAsPath="true"
enable="true"
shutdownTimeout="90"
delayNotificationTimeout="5"
waitChangeNotification="0"
maxWaitChangeNotification="0"
enableHeaderChecking="true"
sendCacheControlHeader="true"
apartmentThreading="false" />

A lot is going on in this single node, but the setting that takes care of the size of the files to be uploaded is the maxRequestLength attribute. By default, this is set to 4096 kilobytes (KB). Simply change this value to increase the size of the files that you can upload to the server. If you want to allow 10 megabyte (MB) files to be uploaded to the server, set the maxRequestLength value to 11264, meaning that the application allows files that are up to 11000 KB to be uploaded to the server.

Making this change in the web.config.comments file applies this setting to all the applications that are on the server. If you want to apply this to only the application you are working with, apply this node to the web.config file of your application, overriding any setting that is in the web.config.comments file. Make sure this node resides between the <system.web> nodes in the configuration file.

Another setting involved in the size limitation of files to be uploaded is the value given to the executionTimeout attribute in the <httpRuntime> node.

The value given the executionTimeout attribute is the number of seconds the upload is allowed to occur before being shut down by ASP.NET. If you are going to allow large files to be uploaded to the server, you are also going to want to increase this value along with the maxRequestLength value.

One negative with increasing the size of a file that can be uploaded is that there are hackers out there who attack servers by throwing a large number of requests at them. To guard against this, you can actually decrease the size of the files that are allowed to be uploaded; otherwise, you may find hundreds or even thousands of 10 MB requests hitting your server.

Client-Side Validation of File Types Permissible to Upload

There are several methods you can use to control the types of files that are uploaded to the server. Unfortunately, there is no bullet-proof method to protect you from someone uploading files that would be considered malicious. You can take a few steps, however, to make this process of allowing end users to upload files a little more manageable.

One nice method you can employ is to use the ASP.NET validation controls that are provided for free with ASP.NET. These controls enable you to do a regular-expression check upon the file that is being uploaded to see if the extension of the file is one you permit to be uploaded.

This is ideal for browsers that allow client-side use of the validation controls because it forces the checking to be done on the client; the file is not uploaded to the server if the signature isn't one you allow. Listing 3 shows you an example of using validation controls to accomplish this task.

Note   The use of validation controls is not explained here. Take a look at Validating ASP.NET Server Controls for a complete explanation of validation controls and how to use them in your ASP.NET pages.

Listing 3. Using validation controls to restrict the types of files uploaded to the server

<asp:FileUpload ID="FileUpload1" runat="server" /><br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click"
Text="Upload File" />&nbsp;<br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
<asp:RegularExpressionValidator
id="RegularExpressionValidator1" runat="server"
ErrorMessage="Only mp3, m3u or mpeg files are allowed!"
ValidationExpression="^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))
+(.mp3|.MP3|.mpeg|.MPEG|.m3u|.M3U)$"
ControlToValidate="FileUpload1"></asp:RegularExpressionValidator>
<br />
<asp:RequiredFieldValidator
id="RequiredFieldValidator1" runat="server"
ErrorMessage="This is a required field!"
ControlToValidate="FileUpload1"></asp:RequiredFieldValidator>

This simple ASP.NET page uses validation controls so that the end user can only upload .mp3, .mpeg, or .m3u files to the server. If the file type is not one these three choices, a Validation control throws an exception onto the screen. This is shown in Figure 4.

Figure 4. Validating the file type using validation controls

Using Validation controls is not a foolproof way of controlling the files that are uploaded to the server. It wouldn't be too hard for someone to change the file extension of a file so it would be accepted and uploaded to the server, thereby bypassing this simple security model.

Adding Server-Side File Type Validation

You just saw an easy way to add some ASP.NET validation server controls to your ASP.NET page to perform a client side validation of the file extension (in just a textual manner). Now let's take a look at how to perform a similar operation on the server-side. This is presented in Listing 4.

Listing 4. Checking the file type on the server

Visual Basic

    Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If FileUpload1.HasFile Then
Dim fileExt As String
fileExt = System.IO.Path.GetExtension(FileUpload1.FileName)

If (fileExt = ".mp3") Then
Try
FileUpload1.SaveAs("C:\Uploads\" & _
FileUpload1.FileName)
Label1.Text = "File name: " & _
FileUpload1.PostedFile.FileName & "<br>" & _
"File Size: " & _
FileUpload1.PostedFile.ContentLength & " kb<br>" & _
"Content type: " & _
FileUpload1.PostedFile.ContentType
Catch ex As Exception
Label1.Text = "ERROR: " & ex.Message.ToString()
End Try
Else
Label1.Text = "Only .mp3 files allowed!"
End If
Else
Label1.Text = "You have not specified a file."
End If
End Sub

C#

    protected void Button1_Click(object sender, EventArgs e)
{

if (FileUpload1.HasFile)
{
string fileExt =
System.IO.Path.GetExtension(FileUpload1.FileName);

if (fileExt == ".mp3")
{
try
{
FileUpload1.SaveAs("C:\\Uploads\\" +
FileUpload1.FileName);
Label1.Text = "File name: " +
FileUpload1.PostedFile.FileName + "<br>" +
FileUpload1.PostedFile.ContentLength + " kb<br>" +
"Content type: " +
FileUpload1.PostedFile.ContentType;
}
catch (Exception ex)
{
Label1.Text = "ERROR: " + ex.Message.ToString();
}
}
else
{
Label1.Text = "Only .mp3 files allowed!";
}
}
else
{
Label1.Text = "You have not specified a file.";
}
}

Now, by using the GetExtension method from the System.IO.Path namespace, you can perform basically the same operation. It is important to note that this doesn't get around an end user's ability to simply change the file extension to something that works and upload that altered file to the hosting server.

Uploading Multiple Files at the Same Time

So far, you have seen some good examples of how to upload a file to the server without much hassle. Now let's take a look at how to upload multiple files to the server from a single page.

No built-in capabilities in the Microsoft .NET Framework enable you to upload multiple files from a single ASP.NET page. With a little work, however, you can easily accomplish this task just as you would have in the past using .NET 1.x.

The trick is to import the System.IO class into your ASP.NET page, and to then use the HttpFileCollection class to capture all the files that are sent in with the Request object. This approach enables you to upload as many files as you want from a single page.

If you wanted to, you could simply handle each and every FileUpload control on the page individually, as presented in Listing 5.

Listing 5. Handling each FileUpload control individually

Visual Basic

If FileUpload1.HasFile Then
' Handle file
End If

If FileUpload2.HasFile Then
' Handle file
End If

C#

if (FileUpload1.HasFile) {
// Handle file
}

if (FileUpload2.HasFile) {
// Handle file
}

This approach works, but there may be instances where you are going to want to handle the files using the HttpFileCollection class instead—especially if you are working with a dynamically generated list of server controls.

For an example of this, you can build an ASP.NET page that has three FileUpload controls and one Submit button (using the Button control). After the user clicks the Submit button and the files are posted to the server, the code behind takes the files and saves them to a specific location on the server. After the files are saved, the file information that was posted is displayed in the ASP.NET page (see Listing 6).

Listing 6. Uploading multiple files to the server

Visual Basic

Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)

Dim filepath As String = "C:\Uploads"
Dim uploadedFiles As HttpFileCollection = Request.Files
Dim i As Integer = 0

Do Until i = uploadedFiles.Count
Dim userPostedFile As HttpPostedFile = uploadedFiles(i)

Try
If (userPostedFile.ContentLength > 0) Then
Label1.Text += "<u>File #" & (i + 1) & "</u><br>"
Label1.Text += "File Content Type: " & _
userPostedFile.ContentType & "<br>"
Label1.Text += "File Size: " & _
userPostedFile.ContentLength & "kb<br>"
Label1.Text += "File Name: " & _
userPostedFile.FileName & "<br>"

userPostedFile.SaveAs(filepath & "\" & _
System.IO.Path.GetFileName(userPostedFile.FileName))

Label1.Text += "Location where saved: " & _
filepath & "\" & _
System.IO.Path.GetFileName(userPostedFile.FileName) & _
"<p>"
End If
Catch ex As Exception
Label1.Text += "Error:<br>" & ex.Message
End Try
i += 1
Loop
End Sub

C#

protected void Button1_Click(object sender, EventArgs e)
{
string filepath = "C:\\Uploads";
HttpFileCollection uploadedFiles = Request.Files;

for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];

try
{
if (userPostedFile.ContentLength > 0 )
{
Label1.Text += "<u>File #" + (i+1) +
"</u><br>";
Label1.Text += "File Content Type: " +
userPostedFile.ContentType + "<br>";
Label1.Text += "File Size: " +
userPostedFile.ContentLength + "kb<br>";
Label1.Text += "File Name: " +
userPostedFile.FileName + "<br>";

userPostedFile.SaveAs(filepath + "\\" +
System.IO.Path.GetFileName(userPostedFile.FileName));

Label1.Text += "Location where saved: " +
filepath + "\\" +
System.IO.Path.GetFileName(userPostedFile.FileName) +
"<p>";
}
}
catch (Exception Ex)
{
Label1.Text += "Error: <br>" + Ex.Message;
}
}
}

The end user can select up to four files and click the Upload Files button, which initializes the Button1_Click event. Using the HttpFileCollection class with the Request.Files property lets you gain control over all the files that are uploaded from the page. When the files are in this state, you can do whatever you want with them. In this case, the files' properties are examined and written to the screen. In the end, the files are saved to the Uploads folder in the root directory of the server. The result of this action is illustrated in Figure 5.

Figure 5. Uploading four files at once to the server from a single ASP.NET page

As you may have noticed, one interesting point about this example is that the states of the file input text boxes are not saved with the postback. You can see this in Figure 5. In ASP.NET, the state of the file-input text boxes cannot be saved because doing so might pose a security risk.

Conclusion

The FileUpload server control provided by ASP.NET is a powerful control that was quite difficult to achieve in the days of Active Server Pages 3.0. This new capability allows your end-users to upload one or more files to your server. Remember, you can control the size of the files that are uploaded by working with settings in either the web.config.comments or web.config file.

  About the author

Bill Evjen is an active proponent of .NET technologies and community-based learning initiatives for .NET. He is a technical director for Reuters, the international news and financial services company based in St. Louis, Missouri. Bill is the founder and executive director of the International .NET Association (INETA), which represents more than 100,000 members worldwide. Bill is also an author and speaker and has written such books as ASP.NET Professional Secrets, XML Web Services for ASP.NET, Web Services Enhancements, and the Visual Basic .NET Bible (all from Wiley).

11月10日

Paging in DataList

Ví dụ lấy trang thứ 5, mỗi trang 10 bài
SELECT TOP 10 [name] FROM (SELECT TOP 50 [name] FROM [tbl] ORDER BY [id] ASC) ORDER BY [id] DESC
Sau đó hiển thị theo chiều ngược của row trong recordset.
Hoặc dùng câu query sau thay thế:
SELECT [name],[id] FROM (SELECT TOP 10 [name],[id] FROM (SELECT TOP 50 [name],[id] FROM [tbl] ORDER BY [id] ASC) ORDER BY [id] DESC) ORDER BY [id] DESC


Introduction

In my previous article, we discussed how to Sort data in a Datalist. Today, we will learn how we can add the paging feature for the datalist. It should be noted that, like DataGrid, DataList does not support inbuilt paging mechanism. The essence of this article is how we make use of the object SqlDataAdapter. This object has a method called, Fill which is used to add or refresh the rows in a DataSet. Actually the method Fill is overloaded. We will be mainly concentrating the one which takes four arguments. The four arguments are DataSet, startRecord, maxRecords and the TableName. Second and third arguments are integer. Where as the TableName is the table name. So, if we say objDV.Fill(objDS, 0, 5, "sales") The dataset will be filled with 5 records and the starting position will be from the first record. First, we are bringing the entire records from the table sales, and then we filter those with the help of startRecord and maxRecords.

For our example, we will consider the table, Sales from the pubs database (SQL Server 2000).

Things that we will be learning in this article.
  1. How to populate a DataList?
  2. How to build the User Interface for Paging in a DataList?
  3. How to make user of the Fill method of SqlDataAdapter?
  4. An alternate solution for the Fill method!
Populating the DataList

For our example, we will take the table SALES in the PUBS Database. Since stored procedures are very much better than inline query, we use a stored procedure called, sp_das_sales_sel, which contains a single SQL statement. The SQL statement would be Select * from pubs.dbo.sales. And finally, we need to bind the DataView to the DataList web server control.

How to build the User Interface for Paging in a DataList?

Apart from the DataList web server control, we will provide user with four hyperlinks for navigation. When the user clicks on any othe four navigation links, we will invoke a server side method which will pulls out the proper records. We will also show the total number of records, total pages and the current page number. < p>

Code for Navigation Links.
<table width=100% align="right">
    <tr>
        <td width=76% align=left>
        <asp:label ID="lblStatus"
        Runat="server"
        Font-Name="verdana"
        Font-Size="10pt" />
        </td>

        <td width=6%>
        <a href="datalistpaging.aspx#this"
        ID="hrefFirst"
        onserverclick="ShowFirst"
        runat="server"><<<</a>
        </td>

        <td width=6%>
        <a href="datalistpaging.aspx#this"
        ID="hrefPrevious"
        onserverclick="ShowPrevious"
        runat="server"><<</a>
        </td>

        <td width=6%>
        <a href="datalistpaging.aspx#this"
        ID="hrefNext"
        onserverclick="ShowNext"
        runat="server">></a>
        </td>

        <td width=6%>
        <a href="datalistpaging.aspx#this"
        ID="hrefLast"
        onserverclick="ShowLast"
        runat="server">>></a>
        </td>
    </tr>
</table>
How it works?

Important Note: The name of the file that I have used in the href property is "datalistpaging.aspx". You should replace this with your aspx filename, unless you keep the filename as myself.

We have four hyperlinks for each navigation. On each of these, we have a OnServerClick event which will be fired immediately when the user clicks the link. For example, when the user click the link, <<, which is for the first page, the method ShowFirst will be invoked. All we have to do in the ShowFirst method is to set the current record position to zero. And ofcourse, we have to bind the datalist. Let us take a look at the methods, ShowFirst and DataBind.

ShowFirst and the DataBind method.
Public Sub ShowFirst(ByVal s As Object, ByVal e As EventArgs)
    intCurrIndex.Text = "0"
    DataBind()
End Sub

Private Sub DataBind()
    Dim objConn As New SqlConnection(ConfigurationSettings.AppSettings("ConnectionString"))
    Dim objDA As New SqlDataAdapter("exec sp_das_sales_sel", objConn)
    Dim objDS As New DataSet()

    If Not Page.IsPostBack() Then
        objDA.Fill(objDS)
        intRecordCount.Text = CStr(objDS.Tables(0).Rows.Count)
        objDS = Nothing
        objDS = New DataSet()
    End If

    objDA.Fill (objDS, Cint(intCurrIndex.Text), CInt(intPageSize.Text), "Sales")

    dList.DataSource = objDS.Tables(0).DefaultView
    dList.DataBind()
    objConn.Close()
    PrintStatus()
End Sub

How it works?

In the ShowFirst method, we are setting the value of intCurrIndex.Text to be zero. intCurrIndex is a hidden label control which keeps track of the current record number. We also do have two more hidden label controls. They are intPageSize and intRecordCount.

In the method, DataBind you can see that, we get the total record count. We are storing this count in the hidden label web server control called, intRecordCount. Then we use the Fill method to retrieve the current page.

An alternate solution for the Fill method!

The major disadvantage of our logic is that, if we have 1000 records in the table, we are bringing all those to our ASPX pages. All we need is the records for our current page. This can be achived by modifying our stored procedure. We should have an identity column in our table. Then, we should pass the starting position and the number of records to be retrieved to the stored procedure. By this way, we will just be bringing in the needed records, which will decrease the network traffic and throughput time.

Sample output of our scenario

Paging in DataList - 25,698 bytes
Fig: Paging in DataList.
Test this Script

Download the code

Click here to download the ASPX page
Click here to download the Stored Procedure

Links

Sorting in DataList

Conclusion

So, that is it. We have a datalist with paging mechanism. Also read my other article which explains adding the sort feature to a datalist.

Send your comments to das@aspalliance.com

11月9日

CSS properties of link

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<style type="text/css">
    body {
    background-color: tan
    }
    h1 {
    color:maroon;
    font-size:20pt
    }
    hr {
    color:navy
    }
    p {    font-size:11pt;    margin-left: 15px}
    a:link {color:green}
    a:visited {color:yellow}
    a:hover {color:black}
    a:active {color:blue}
</style>
</head>
<body>
    <h1>This is a header 1</h1>
    <hr /> <p>You can see that the style sheet formats the text</p>
    <p><a href="http://www.w3schools.com" target="_blank">This is a link</a></p>
</body>
</html>
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.