Creating a ASP.NET Rounded Panel

By Tony - Last updated: Friday, March 20, 2009

These days using a Rounded Panel on your web site is almost a given. Here is an example to creating a Rounded Panel that inherits from System.Web.Ui.Panel, in a WebControls class library.

First thing I did was fire up Jasc Paintshop Pro and created some rounded rectangles (with a 4px radius) … then I cut the corners off, and pasted all of them into a new image (16×4) [its a PNG with a transparent background]

The Image I used for the corners (4corners-c.png) [the image go in your web project]

4corners-c

The C# code [this goes in your class library]

using System.Web.UI;
using System.Web.UI.WebControls;

namespace MyWebControls
{
    [ToolboxData(
        "<{0}:RoundedPanel runat=\"server\"></{0}:RoundedPanel>")]
    public class RoundedPanel : Panel
    {
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            writer.WriteBeginTag("table");
            writer.WriteAttribute("class", "RoundedPanel");
            writer.WriteAttribute("cellpadding", "0");
            writer.WriteAttribute("cellspacing", "0");
            writer.Write(Html32TextWriter.TagRightChar);

            writer.WriteBeginTag("tr");
            writer.Write(Html32TextWriter.TagRightChar);

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "tl");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "top");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "tr");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteEndTag("tr");
        }
        public override void RenderEndTag(HtmlTextWriter writer)
        {
            writer.WriteBeginTag("tr");
            writer.Write(Html32TextWriter.TagRightChar);

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "bl");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "bottom");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "br");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteEndTag("tr");

            writer.WriteEndTag("table");
        }
        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.WriteBeginTag("tr");
            writer.Write(Html32TextWriter.TagRightChar);

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "left");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "content");
            writer.Write(Html32TextWriter.TagRightChar);
            base.RenderContents(writer);
            writer.WriteEndTag("td");

            writer.WriteBeginTag("td");
            writer.WriteAttribute("class", "right");
            writer.Write(Html32TextWriter.TagRightChar);
            writer.Write("<div style='width:1px;height:1px;overflow:hidden;'></div>");
            writer.WriteEndTag("td");

            writer.WriteEndTag("tr");
        }
    }
}

I chose to inherit from Panel, that way I didn’t have to deal with the complexities of creating a Container Control (a control than can contain other controls), also you can treat my panel as a regular Panel, so your code behind pretty much can stay the same.

You can see that I am using some CSS classes for the styling, you could extend those string literals as public properties if you didn’t want the class names to be hard coded.

 

The CSS [this goes in your web project]

.RoundedPanel
{
}
.RoundedPanel .tl
{
    background-image: url("images/4corners-c.png");
    background-repeat: no-repeat;
    width:4px;
    height:4px;
}
.RoundedPanel .top
{
    border-top: 1px solid #c0c0c0;
    height:3px;
}
.RoundedPanel .tr
{
    background-position: -3px 0px;
    background-image: url("images/4corners-c.png");
    background-repeat: no-repeat;
    width:4px;
    height:4px;
}
.RoundedPanel .left
{
    border-left: 1px solid #c0c0c0;
    width:4px;
}
.RoundedPanel .content
{
}
.RoundedPanel .right
{
    border-right: 1px solid #c0c0c0;
    width:4px;
}
.RoundedPanel .bl
{
    background-position: -8px 0px;
    background-image: url("images/4corners-c.png");
    background-repeat: no-repeat;
    width:4px;
    height:4px;
}
.RoundedPanel .bottom
{
    border-bottom: 1px solid #c0c0c0;
    height:3px;
}
.RoundedPanel .br
{
    background-position: -11px 0px;
    background-image: url("images/4corners-c.png");
    background-repeat: no-repeat;
    width:4px;
    height:4px;
}

 

Also … if you wanted to you could embed your images and CSS in your WebControl library … but I will leave that to another post. (hint search for Page.ClientScript.GetWebResourceUrl())

Filed in .NET Programming, ASP.NET, Web

ADO.NET Entity Framework

By Tony - Last updated: Tuesday, March 3, 2009

I just started reading Programming Entity Framework 

The subjects include:  Data Binding with WPF, LINQ to Entities Queries, Utilizing the ASP.NET EntityDataSource Control, Using Entity Objects with Web and WCF Services, Using the Entity Framework with n-Tier Windows Forms or WPF Applications, a bit on Data Transfer Objects (DTO), Customizing Entities, Using the Entity Framework with n-Tier ASP.NET Applications, Using Stored Procedures with the EDM, Handling Entity Framework Exceptions, Performance, Security, Multithreaded Applications, Data Binding with Windows Forms . there are many other topics discussed

So far I love the layout of the book. I also looked at Professional ADO.NET 3.5 with LINQ and the Entity Framework (Wrox Programmer to Programmer) (Paperback) … but I decided to go with this newer Programming Entity Framework book …

Filed in .NET Programming, ASP.NET, Databases

How To Burn ISO Images on Windows Server 2008

By Tony - Last updated: Thursday, September 25, 2008

You can use the CDBurn.exe tool from Microsoft. It is included in the Windows Server 2003 Resource Tools.

You can even use this tool to erase CDRW discs.

Command Line Syntax:

Usage:

cdburn <drive> -erase [image [options]] 
cdburn <drive> image [options]
Options:
    -erase            Erases the disk before burning (valid for R/W only)
    -sao              Writes the image out in "session at once", or cue 
                      sheet, mode (default is "track at once")
    -speed            Speed of burn, or ‘max’ for maximum speed
    -imagehaspostgap  Use if your image already contains a 150 sector postgap

The [image] must be provided unless the -erase flag is set.
If both an image and -erase are provided, the media will be
erased prior to burning the image to the disc.

Filed in Uncategorized

LINQ, SqlMetal, Nesting The Generated Code File

By Tony - Last updated: Monday, July 7, 2008

LINQ is really cool, SqlMetal has been my code generator of choice (for a book on LINQ, SqlMetal and all of the cool new features)… I like to keep my class file names the same as the class contained in the file. Since SqlMetal generates partial classes, and we don’t want to modify the generated file directly, well now we are stuck creating a new file name that doesn’t match our naming convention.  (note: you could stick the generated code in a generated directory or something, which is what I had done in the past… UNTIL NOW :) )

Enter the DependentUpon element tag in your project file. Real quick open a Windows Forms, or Web project. Notice how the webforms or windows forms classes have a *.designer.cs code file nested underneath the actual form. Not only does it help us keep the files grouped together, but it allows us to keep naming conventions and keeps the project solution clean… Now that you have your project open, unload it, then Edit the project file directly (so you can see the XML)… Scroll down to the Compile items collection… Ah Ha! do you see that? Its the DependentUpon element nested underneath the *.designer.cs files.

You can use this for your Linq DataProvider class library projects. Here’s the system that I use.

A Regenerate batch file (DbGen.cmd)

sqlmetal ​/server:.\sqlexpress ​/database:website ​/code:website.sqlmetal.cs ​/namespace:Devprise.dataProvider ​/views

Modify your csproj file to use the DependentUpon directive on your generated code file.

  <ItemGroup>
    <Compile Include=”website.cs” />
    <Compile Include=”website.sqlmetal.cs”>
      <DependentUpon>website.cs</DependentUpon>
    </Compile>

All of your custom code goes into the base named code file (website.cs in my example)

Filed in .NET Programming, ASP.NET

How To Install Windows Live Writer on Windows Server 2008

By Tony - Last updated: Wednesday, June 18, 2008

So this is my first post using Windows Live Writer from a Windows Server 2008 workstation.

I was not able to install Windows Live Writer 2008 on my server workstation, it would give the error:

Sorry, Windows Live programs cannot be installed on Windows Server, Windows XP Professional x64 Edition, or Windows operating systems earlier than Windows XP Service Pack 2.

BUT you CAN install the Technical Preview version on Windows Server 2008 !!!

Need a good book on Windows Server 2008, see Windows Server 2008 Unleashed

Filed in Web

How To Copy / Clone a Hyper-V Virtual Machine

By Tony - Last updated: Tuesday, June 17, 2008

You can create a copy or clone of an existing virtual machine (VM) quite easily in Hyper-V … The process is a little different than you might think though. The basic procedure is to export and import a virtual machine. I use my VM’s primarily for separate development sandboxes and test machines, so here’s the steps I used:

  1. Sysprep the guest VM (for windows machines)
  2. Shut down the guest
  3. Rename the VM to “Dev Ws - Base” (in Hyper-V Manager)
  4. Hyper-V Export Virtual Machine
  5. Rename the original VM back to the original name
  6. Make a copy of the exported directory in windows explorer (optional if you want more than one copy) (i used robocopy from an administrator command prompt [robocopy /s "Dev Ws - Base" "Dev Ws - SplendidCRM"])
  7. Import the one of the directories
  8. Rename the new VM to your new VM name, in my case it was “Dev Ws - DotNetNuke”

Now you should have multiple copies of your original VM. Check out Microsoft Windows Server 2008: Implementation and Administration for more information on Hyper-V!

Oh and if you want to move the exported folder for any reason before you re-import it, you might need to stop the Hyper-V service, other wise you may get a “destination folder access denied” error box.

If you want a scripted solution to this (like to make lets say 10 machines) check out this post.

Filed in Hardware

Excel ODBC Driver for Windows Server 2008 (64 Bit)

By Tony - Last updated: Tuesday, June 10, 2008

So I’m running Windows Server 2008 as a development workstation. I ran into some trouble with a custom .NET application that imports data from Excel files using the ODBC driver.

Error Message in .NET

ERROR [IM002] [Microsoft] [ODBC Driver Manager] Data source name not found and no default driver specified

We are using this ODBC connection string (found on connectionsstrings.com):

Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=C:\MyExcel.xls;DefaultDir=c:\mypath;

After much research on the issue, it turns out the Excel ODBC drivers are 32 bit. So you need to change your Visual Studio platform to be x86 (to force 32bit) … mine was set to “Any CPU”

From what I can gather about the issue here, is that if your application is running in 64 bit mode, then when it creates an odbcConnection, that will also be running under 64 bit (makes sense so far) … so for any drivers that you have that are 32 bit they will not be accessible. Thus you get an error stating “data source name not found”

see this forum post about running sql server 2005 64 bit … it doesn’t say anything about Excel, but I think the principle applies

That’s it! Hope this helps.

For some light ;) reading on Windows Server 2008

Filed in .NET Programming

Small Simple Plug-In to Burn ISO’s in Windows Vista

By Tony - Last updated: Monday, June 2, 2008

For a very small simple and easy to use ISO burner for Windows Vista (and XP), check out ISO Recorder by Alex Feinman … It works like a Microsoft PowerToy. I love it!

Filed in Audio / Video, Showcase

HowTo Filter System.IO.Directory.GetFiles with Linq

By Tony - Last updated: Friday, May 30, 2008

Here we are going to see an easy way to enumerate files in a directory, filter the files with Linq, then bind the results to a ASP.NET repeater control. We will show you the old .NET 1x way of doing this, then the new and improved Linq way of doing this.

I had a method that would return a DataTable as results, then bind it to a ASP.NET Repeater control to display the file list of Exception Reports.

Old .NET 1.1 way of filtering a GetFiles list and returning as a bindable object

DataTable dtFiles = new DataTable();

dtFiles.Columns.Add("FullName", typeof(string));

dtFiles.Columns.Add("FileName", typeof(string));

 

foreach (string file in Directory.GetFiles(Server.MapPath("~/App_Data")))

{

    if (!file.Contains("ErrorReport"))

        continue;

    DataRow row = dtFiles.NewRow();

    row["FullName"] = file;

    row["FileName"] = System.IO.Path.GetFileName(file);

    dtFiles.Rows.Add(row);

}

 

this.repeaterFiles.DataSource = dtFiles;

this.repeaterFiles.DataBind();

 

Here is how to filter your GetFiles results with Linq

var fileList = from file in Directory.GetFiles(Server.MapPath("~/App_Data"))

               where file.Contains("ErrorReport")

               select new

               {

                   FullName = file,

                   FileName = System.IO.Path.GetFileName(file)

               };

this.repeaterFiles.DataSource = dtFiles;

this.repeaterFiles.DataBind();

You can see this is much cleaner, no need to create a DataTable with the results. By using the "select new" you are basically creating a collection with two properties (FullName, FileName) on the fly.

I found Pro LINQ to be an excellent read on the Linq subject.

Filed in .NET Programming, ASP.NET, Web • Tags:

Querying Selected Items From ListItemCollection Using Lambda Expressions

By Tony - Last updated: Tuesday, May 27, 2008

You can use Lambda expressions and the new extensions provided in the .NET framework 3.5 to filter your specialized collections like the ListItemCollection (used in ASP.NET ListBox controls).

I found this great usage for lambda this weekend when posed with a problem using a ListBox control with a SelectionMode of Multiple. If you’ve ever worked with the ListBox before (and I think you have), getting the single SelectedValue or SelectedIndex is a piece of cake. When you need to get all the selected items, well now you’re probably thinking about using a foreach loop to find the selected items, list this:

Two ‘old school’ solutions to get Selected items from a ListItemCollection

Simple foreach loop for finding Selected items in a ListItemCollection

List<ListItem> selectedItems = new List<ListItem>();
foreach (ListItem itm in lboxItems.Items)
{
    if (itm.Selected)
        selectedItems.Add(itm);
}

Or you’re thinking about using an Iterator pattern here, made easy with .NET framework 2.0 and the lovely generics it brought us:

More advanced Iterator patten for returning only selected items

private IEnumerable<ListItem> selectedItems(ListBox lbox)
{
    foreach (ListItem itm in lbox.Items)
    {
        if (itm.Selected)
            yield return itm;
    }            
}

Welcome to Lambda and .NET framework 3.5 !!!

Can you tell that I am overly excited about this?

So there is two more ways to do this:

How to get only the selected items from a ListBox control using Linq

var selectedItems = from li in lboxItems.Items.Cast<ListItem>()
    where li.Selected == true
    select li;

You see we have to first Cast the specialized ListItemCollection to a generic List<ListItem> collection before it can be used in a Linq query (for more info on linq this book really helped me on the subject). You may even want to finally encapsulate the (from …. select li) with parenthesis and then apply a .ToList(), that way it will be typed as a Generic List<ListItem> collection.

How to get only the selected items from a ListBox control using Lambda Expressions

List<ListItem> selectedItems =
    lboxItems.Items.Cast<ListItem>()
    .Where(itm => itm.Selected == true).ToList();

You see we also had to first Cast the specialized ListItemCollection to a generic List<ListItem> collection first to get the extensions (Where and ToList) … now in the Where method is the place that we finally see the lambda expression come to light, this basically is an easier way to express an anonymous delagate function, if you’ve never used one before, then feel lucky that your here now with the availablility of lambda!!!

 

You can download a working Lamda demo against ListItemCollection here

 

I highly recommend ASP.NET 3.5 Unleashed which talks a lot about Linq and Lamda expressions.

Filed in ASP.NET, Web • Tags: