and has 0 comments
Microsoft has now released Orcas into the wild with a Community Technology Preview download. Links: Orcas CTP download, Orcas CTP - Development Tools for WinFX.

A quick intro interview with Sam Guckenheimer, Lead Product Planner for Orcas:
Orcas and the Future of Visual Studio

CSS Friendly ASP.NET 2.0 Control Adapters is a little project run by Brian Goldfarb and what it does is use the power of the ControlAdapter object to change the way ASP.NET controls get rendered. They use CSS layout to control the way things look and try to remove the old table based format.

While this could be a good thing in some situations, it could be harmful in others like low resources or weird changes in the CSS laws. I let you decide for yourselves. And while the ControlAdapter approach is very elegant, I've used this concept in creating my own controls when needed by overriding ASP.NET classes and using simpler code. Also, these Control Adapters are in Beta 2 stage. Major changes are still in the works.

So don't trust it blindly, but do check it out, as it is a worthy and honorable quest :)

The GridView is nothing more than an oversized DataGrid. The internal concept is completely rewritten, as far as I see, though. For example, Columns are not called columns anymore, they are DataControlField. Well, I stumbled upon one situation where I needed to format the autogenerated columns in a GridView. Normally, you could take the Columns collection and change the DataFormatString property for each column, but autogenerated columns (or AutoGeneratedField) are not part of the Columns collection. More than that, AutoGeneratedFields are nothing more than BoundFields with lots of useless restrictions on it like being a sealed class and throwing errors when trying to change some properties (like DataFormatString).

The first step is getting hold of the autogenerated column. Luckily the GridView control has a virtual method called CreateAutoGeneratedColumn which returns a AutoGeneratedField. So create a control that inherits GridView, override this method, take the generated field in the base method, change DataFormatString. I couldn't find any way to do that except with reflection. I noticed that the value of the DataFormatString property was stored in the ViewState of the AutoGeneratedField, so I used reflection to get to it, then I changed the value.

This is the code:
protected override AutoGeneratedField CreateAutoGeneratedColumn(
AutoGeneratedFieldProperties fieldProperties)
{
AutoGeneratedField field =
base.CreateAutoGeneratedColumn(fieldProperties);
StateBag sb = (StateBag)field.GetType()
.InvokeMember("ViewState",
BindingFlags.GetProperty |
BindingFlags.NonPublic |
BindingFlags.Instance,
null, field, new object[] {});
sb["DataFormatString"] = "{0:N}"; //or the format string you prefer
field.HtmlEncode=false; //see update
return field;
}


Update:
The BoundField object formats values differently depending on html encoding. If the html encoding is enabled, then the value is transformed into a string, then the formatting is applied. That means that number formatting will NOT work when html encoding is true.
That is why I've added the field.HtmlEncode=false; line above. A more secure option would be to make the HtmlEncode property depend on the field.DataType.

Update2:
While this works, I don't recommend doing it like that. I am using it because I have custom user controls that inherit from the GridView and I need to cover the AutoGeneratedColumns=true case. It is much easier to generate your columns yourself from the DataSource using BoundField objects (Or any other DataControlField objects) that you add to the GridView.Columns collection.

GridView Export to Excel Problems

This guy researched why simple methods like export datagrid to Excel don't work with GridViews or other controls. I have also stumbled on this stupid error when trying to use RenderControl to get the output of a UserControl.

Apparently, the entire problem lies with the
Page.VerifyRenderingInServerForm Method
which throws an exception if the page is not currently in the render phase of page processing, and inside the <form runat=server> tags.

Luckily it can be overridden. Here is the bug posting at Microsoft and their suggested solutions. Microsoft removed the page, so I can't show it to you.

This is the actual code for the method in the Page control in NET 2.0. Just override the hell out of it.
public virtual void VerifyRenderingInServerForm(Control control)
{
if (this.Context == null || base.DesignMode) return;

if (control == null)
{
throw new ArgumentNullException("control");
}
if (!this._inOnFormRender && !this.IsCallback)
{
throw new HttpException(System.Web.SR.GetString("ControlRenderedOutsideServerForm", new object[] {
control.ClientID,
control.GetType().Name
}));
}
}

Accessing Row based data in an efficient and maintainable manner - The Code Project - C# Database

This is a nice and simple article about accessing data from a lot of datarows. While using the string index will make the code more readable, using the integer index will make the code faster. The solution? Get the numeric indexes at the beginning of the loop, based on string indexes. Assert the indexes exist for better debugging. Very elegant. Also, check out the user comments, which are pretty good and to the point.

Code example:

int customerIDIndex = table.Columns.IndexOf("customerID");
int customerFirstNameIndex = table.Columns.IndexOf("firstName");
int customerLastNameIndex = table.Columns.IndexOf("lastName");

System.Diagnostics.Debug.Assert(customerIDIndex > -1,
"Database out of sync");
System.Diagnostics.Debug.Assert(customerFirstNameIndex > -1,
"Database out of sync");
System.Diagnostics.Debug.Assert(customerLastNameIndex > -1,
"Database out of sync");

foreach(DataRow row in table.Rows){
customer = new Customer();
customer.ID = (Int32)row[customerIDIndex];
customer.FirstName = row[customerFirstNameIndex].ToString();
customer.LastName = row[customerLastNameIndex].ToString();
}//end foreach

How to include a header on each page when printing a DataGrid - The Code Project - .NET

There is a simple solution for printing tables with repeating headers on each printed page. It involves CSS styling of the THEAD section of a table. Unfortunately, neither DataGrids nor GridViews render the THEAD tag. Somehow, Microsoft seems hellbent against it. So either create a control that renders THEAD, then add "display:table-header-group;" to the THEAD style, or use this Javascript function:



function AddTHEAD(tableName)
{
var table = document.getElementById(tableName);
if(table != null)
{
var head = document.createElement("THEAD");
head.style.display = "table-header-group";
head.appendChild(table.rows[0]);
table.insertBefore(head, table.childNodes[0]);
}
}
Update:
Building a GridView, DataGrid or Table with THEAD, TBODY or TFOOT sections in NET 2.0

Using SQL Server instead of Access files:
1. Run aspnet_regsql.exe (from the NET Framework 2.0 folder)
2. Add to web.config (inside the configuration tag):
<connectionStrings>
<remove name="LocalSqlServer"/>
<add name="LocalSqlServer" connectionString="Data Source=localhost;Initial Catalog=aspnetdb;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
(that's because LocalSqlServer is already defined by default. Really dumb)
3. Go to the Website menu in Visual Studio -> ASP.NET Configuration and create users, roles and access rules.

Logging out programatically:
FormsAuthentication.SignOut();

Changing settings for the membership (in system.web section):
<membership defaultProvider="CustomizedProvider">
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="/"
requiresUniqueEmail="false"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
commentTimeout=""/>
</providers>
</membership>

I had problems with WindowsFormsParkingWindow and a lot of the references on the web pointed to this blog article. Unfortunately, the page was not available when I started searching for it. The only place I could find it was google cache, god bless their big googly hearts :) Therefore I am reprinting the content here, maybe it helps people:

=== WindowsFormsParkingWindow a.k.a The devil ===

I have been working on an application for a few weeks and suddenly it started freezing up for no reason. After copious amounts of swearing and breaking keyboards I found a hidden window in the windows task list. It was called - WindowsFormsParkingWindow. My new worst nightmare.

Nothing seemed to stop this issue from killing my program. After more swearing and cursing I found that this error happened after ALT-Tabbing away from my app and back into it. The parking window would appear and my app would die. I ran WinSpy++ and made the hidden window visible. Behold the glory of the following...

The hidden window contained a user control that I had previously removed off the form. This might not make sense to you now but let me explain the significance. When you remove a control from a form/panel, it gets put onto a WindowsFormsParkingWindow until you put it back onto the panel/form. So the WindowsFormsParkingWindow is kind of like an intermediate place windows keeps user controls before they are put into containers.

You might ask now - "What has that got to do with my app freezing?" Well, I'll tell you exactly why... Because when you remove a control from a panel/form and it has focus, the focus stays on the control (which is now on an invisible form). That's why events fail to fire and the app becomes unresponsive.

The solution? Easy...

Instead of using pnlParent.Clear() or just removing the control you need to do the following:

1. Remove the focus from the current user control by setting it to the parent form.
2. Remove the desired user control by using the ParentControl.RemoveAt( indexOfUsercontrol )

This should clear up the issue.

I somehow managed to add to one of my Visual Studio 2005 Web Projects a webservice that had the code written "inline" meaning the <%@ WebService Language="C#" Class="WService"%> tag, followed by the C# code. While Visual Studio has a decent Intellisense functionality in asmx files, ReSharper doesn't. So I felt the need to move the code into a codebehind file. You would think that adding the Codebehind="WService.amsx.cs" would be enough. No, it isn't! As the codebehind model for VS is to have the codebehind in a compiled dll, an error like "Cannot create type WService" will annoy the hell out of you. The solution is to add the cs file into the App_Code directory.
<%@ WebService Language="C#" Class="WService" Codebehind="~/App_Code/WService.asmx.cs"%>

I've tried compiling and using a dll from the net for a Pocket PC and, even if the compilation of the source worked, when trying to add it as a reference, I got an error and the dll would not show in the references. However, a lot of other errors occurred later on, as if the dll was still referenced. Reading the csdproj file directly, I noticed that the reference to the dll was there, but that every time the project was loaded, the same error occurred and the reference did not show. The only solution is to remove with a text editor the XML entry from the csdproj file.

Also, VS2003 hangs periodically after a few debug-deploy cycles, usually when trying to stop debugging, using 100% CPU and freezing. This might also be related with version 2.0 of ReSharper which I have installed, but somehow I doubt it, cause I love the guys at JetBrains! :) The only solution is to kill the process, which will close VS2003, then restart it and reload the project.

Another issue is with the file on the Palm being in use while you try to deploy. The solution is to get to the Palm Control Panel, go to Memory, select the Running Programs, kill any program that has the same name as the program you want to deploy and anything that looks like "Client".

There are other issues, but I don't care to remember them all B-)

How to: Reference ASP.NET Master Page Content:
You must use a MasterType tag in each page to define the exact master page used. After that, all public members and properties in the MasterPage will be available in code as
Master.PropertyOrMember="RightHand";

Loading a Web User Control dynamically is rather easy: MyUserControl muc=(MyUserControl)Page.LoadControl("MyUserControl.ascx"); As a side note, I use this with AJAX, to load a user control, extract the rendered HTML and return it to be added javascriptmagically in a panel on the page.
However, when trying the same piece of code on Visual Studio 2005 with NET 2.0, I got numerous errors that MyUserControl was not found (The name 'MyUserControl' does not exist in the current context). Look, you moron, it's in the solution!! Anyway, I searched the web and discovered that even if I do load the web user control dynamically, I should also add a <@ register..> tag to the aspx, as if I would have the user control on the page.
Easiest way is to move the user control on the page, copy the register tag to the clipboard, undo the user control insertion, paste the register tag back.

Yesterday I had this problem where I needed to access the Session object from a webcontrol. I used HttpContext.Current.Session, after checking is HttpContext.Current was null. Then I've encountered a problem where HttpContext.Current was NOT null, neither were the Application, Response, Request and Server child objects, but Session was null.

After half an hour of searching on the web, I've decided to drill down on the problem and see what were the conditions under which it appeared. It seems someone had used the control in a UserControl that was loaded in the member declaration of the page. In other words, my WebControl was trying to access the Session object inside the constructor of a page. Apparently, the Session object is null in the constructor. Don't use private MyObject obj=new MyObject() anyway, since it breaks the separation of declaration and code, and don't try to access the Session object in the page Ctor.

My solution, after changing the offending piece of code, was to also change the WebControl to check if Session was null and if so, work without it. I also added a Debug.WriteLine('you are an idiot') message, for anyone encountering the same problem.

Getting back to programming, I am starting a small, but premiere project for Palm. These devices seem to be the work of the devil. The particular model I am programming for is something with a resolution of 240x320, with 64MB storage AND memory and with a 300Mhz processor.

Why?! When all computer screens are rectangular, with the width larger than the height, they make a device that is exactly the oposite. I mean, I understand they are meant to be hand held and all hand held devices are longer than they are wide, but it's still annoying.

Also, if I try to find a PC memory that is less than 256MB I would probably be forced to buy it second hand, yet they make a 64MB model? This also applies to the processor. Are they spending more money to make slower processors or is it just me seing things wrong?

Anyway, I found that working with DataSets in this environment is just awful. I started with a simple test project, 20000 rows in a 3.5MB XML file, loaded into a DataSet then displayed in a datagrid. First, the whole thing went out of memory and froze, then, when I fixed the memory problem by creating my own binary format and loading the file my way (oh yeah, I can see the roots of a XML sucks rant) the datagrid was very unwieldy.

Therefore I devised a ClusterGrid, something that shows clusters of rows in a datagrid and you just drill down and up on it. On my data, finding a customer in a 20000 rows table is 4 clicks away. First it shows 10 rows, representing clusters of 2000 people ordered alphabetically (ex: first cluster, from Alice to DeeDee). You click (or press with the finger, I have no idea how an actual Palm functions, I am using the emulator in Visual Studio 2003) on a cluster, you get another 10 clusters, with 200 people each. Then 20, then 2. Four clicks. Works like a charm. It seems a better deal than the scroll of the datagrid and I wonder why I haven't seen this before.

A small tip regarding the Palm Emulator. The default configuration is set on 32MB of memory+storage. If you want to at least have a functional program, increase it in the VS options, in the Mobile Devices tab. I couldn't make it larger than 64MB for whatever reason, but I never needed more and 32 is way too low.

This is a nice link about how to convert a UserControl to a WebControl.
Convert a Usercontrol to a WebControl - The Code Project - ASP.NET

Of course, afterwards it is best to take the time to really think the WebControl through, but for quick conversions like "I want a web control that has a datatable and a graph and another that is a textbox and a validator" it is perfect. Haven't really tested the result on real life user controls.