Wednesday 31 May 2006

Convert a Usercontrol to a WebControl

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.

Monday 29 May 2006

CSS Style Sheets Fundamentals

I don't count myself as a web developer. Maybe what I'm saying here is really basic, but here it goes.

1. CSS Style Sheets are good. Because you can change a lot from the file without changing the site. One could even imagine a complete site makeover only from the style. Remember that style can have color, font size, div position, borders, anything one can think of and it's not in Javascript :)

2. As a corolary to the first rule, style tags and color attributes and stuff like that inside the html file are NOT good. A colleague of mine has submited the idea that there are exceptions to this, like horizontal alignment in table columns and similar basic things. But I say NO! :) If there was a requirement for a certain column to be aligned differently, then it belongs to another style class, even if it's only one column in a thousand columns with the same alignment. I do admit that it's difficult and annoying to copy all the attributes of a class to another just to change something as trivial as the text color. Which brings me to point 3.

3. You can't nest or inherit CSS classes, which is really dumb. I mean, I want a base class to contain text font and color and everything and I want to create another class that says "I am like class1, but with bold font". You can't do that as far as I know, but you can combine classes. An element can have a class="redFont blueBoldFont" which will combine the two CSS classes, and they will overwrite each other. In this case the font will be blue and bold, as the blue color will override the red.

4. CSS classes can be selective. For example .redFont td { color:red; } will apply only to table cells within elements with the redFont class. That is different from the td.redFont notation, which tells what will happen with table cells that have the redFont class. I would suggest avoiding this type of notation if possible. Also, one can somewhat separate the behaviour of a class inside another class: .redFont .blueBoldFont { color:magenta; } in a css file or within a style tag will signify that the blueBoldFont class within the redFont class will have magenta color. Everything else being a combination of the two mentioned classes. This is a little akward, but it works. Warning! the notation .class1.class2 works in Internet Explorer only. The proper notation is the classes names preceded by a dot and separated by spaces.

5. One cannot configure custom html attributes or javascript events in style. That is a hinderance, but I don't know if adding it would have helped things. I mean, I do want to configure all the elements having a draggable class to have special mousedown and mouseup events, but this can also be done from javascript.

What does this mean? It means that a well designed site will have ALL the styling, even the position and size of movable elements, in a CSS file, as it will have all the Javascript in a JS file. This kind of file separation insures that the styling can be changed independently from the Javascript code and the HTML source. It also means that when designing a Web Control, creating a complicated style system for all its elements is not necessary. Just give a default class to each pertinent html element and then give the entire control a single configurable CSS class. Then combine classes to style each element.

Tuesday 23 May 2006

Cancel, kill, murder a javascript event

Use this in a Javascript event handler to stop the event from continuing. Some events cannot be stopped, but the ones that can will be stopped by this in any browser.

function murderEvent(evt) {
evt.cancel=true;
evt.returnValue=false;
evt.cancelBubble=true;
if (evt.stopPropagation) evt.stopPropagation();
if (evt.preventDefault) evt.preventDefault();
return false;
}

The 1918 Spanish Flu pandemic

I spoke about it in a previous post and I realised that this is an important issue, not just a side note. I never learned about it in school, nor did a lot of my friends. I've researched it and I found out that it's not in the American history books either. It's not even Spanish, it came from the US, and as Spain was not in the war at the time, they didn't have war time censorship and talked freely about it. That's why it came to be known as Spanish. Funny enough, in Spain it was called the French Flu.

But what was it? How did it happen? Apparently it was a type of avian influenza, just like the one we panic so much now, it emerged in an American military fort, then it spread as the soldiers were moved from place to place. When they came to fight in Europe, it spread there as well. The effects are very swift destruction of lung tissue which causes the patient to drown in his own fluids and the flu affected more the young and the fit, not the old people.

Opinions are divided, some say as much as 100 million people have died, while others give a more conservative value of 40-50 million. Compare that with the 16 million people killed in the entire World War I which just ended, and you realise the magnitude of the issue.

So, again, why have so little people heard about it? It is a horrible disaster, yet it is treated as a historical side note. I haven't heard of one movie that used it as a script idea. What is going on? Was the "war time censorship" so efficient? But then why did it not emerge as a huge thing afterwards?

As a history drive it was extremely powerful, for example US president Wilson who negociated the end of the war had it. Maybe if he had been stronger mentally, he wouldn't had let Clemenceau, the French counterpart, have his way in imposing harsher conditions on Germany. That, in turn, could have reduced the German motivation for starting World War II.

Even more interesting is how the disease disappeared. They didn't really have a cure for it, it just vanished, after killing so many. The mortality rate was rather small, too. The new avian influenza has a 66% kill ratio in humans so far.

IPostBackDataHandler, Web controls that keep their data together

Making a Web Control is not complicated. but things get weird when they need to postback values. Well, how does a Web Control postback? It implements the Interface IPostBackDataHandler which exposes two methods:

public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
public void RaisePostDataChangedEvent()

RaisePostDataChangedEvent should be called by LoadPostData, so you can just ignore it if you don't need it.
LoadPostData will not be called unless the WebControl is registered with the page for postback. I do this in the override of OnInit:
if (Page != null) Page.RegisterRequiresPostBack(this);
postDataKey is the "identifier" of the control, meaning that weird UniqueID with ":" instead of "_" separating the parent control ids from the children. You can use it or not.
postCollection is the Request.Form collection, The collection of all incoming name values.

example, a Label that also adds a hidden input field and handles the postback of that field value. Try changing the value from javascript and the text value will also change on postback.

public class UselessLabelPostback:Label,IPostBackDataHandler
{
private bool changed;
public bool Changed
{get { return changed; }}

protected override void OnInit(EventArgs e)
{
base.OnInit (e);
if (Page != null) Page.RegisterRequiresPostBack(this);
changed=false;
}

protected override void Render(HtmlTextWriter writer)
{
base.Render (writer);
HtmlInputHidden hih=new HtmlInputHidden();
hih.ID=this.ClientID+"_hiddenField";
hih.Value=this.Text;
hih.RenderControl(writer);
}

public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
string s=postCollection[this.ClientID+"_hiddenField"]; //not using postDataKey
if (s!=null)
{
s=HttpContext.Current.Server.HtmlDecode(s);
if (s!=Text) RaisePostDataChangedEvent();
this.Text=s;
return true;
}
return false;
}

public void RaisePostDataChangedEvent()
{
this.changed=true;
}
}

Important:
This is a control inherited from a Label, that's why I chose to render the hidden input manually. This has a few side effects. For example, the id of the label will be ucIPostBackTest1_UselessLabelPostback1 if the control is inside a User Control called ucIPostBackTest1. The id of the hidden field will be ucIPostBackTest1_UselessLabelPostback1_hiddenField only because I used the ClientID of the label when I manually set the field ID. For the same reason the name (the name attribute of a html item is the one that gives the postback identifier, not the id) will be the same.

The way to do it when starting from scratch is to add extra controls in the CreateChildControls() overriden method, use EnsureChildControls() in the PreRender or Render methods and the web control will render them all. Here the names and ids of the rendered child controls will differ and this is where the postDataKey comes in. But that's another story.

Sunday 21 May 2006

The Holocaust sucks!

Third episode from the internationally acclaimed series World that Sucks.
Normally, the good hearted person that I am (yeah, right) would flinch at the idea that 6 million people were moved to special extermination camps and, well, exterminated. But when we talk the Jewish Holocaust, I just can't feel anything. They whined and continue to whine so much about this, that it lost all appeal. That they do almost the same thing with Palestinians is just the tip of the iceberg.
What offends me even more are the number of Hollywood movies and other types of popular shows that are shedding crocodile tears over this. OK, it happened. More atrocious things also happened. A lot more Russians died in the same war, does anybody cry for them? No, they were communists, fuck them! 50 million people died in the Spanish Flu pandemic. Do we hear of it anywhere else than on Discovery Channel? No.
I bet the whole Holocaust Hoax idea came from some guy that couldn't take it anymore. So much bullshit was thrown that it was impossible for any of that to be true.
So my conclusion is that the Holocaust sucks. Any mention of it, as a corollary of the Goodwin law, should end any conversation and disqualify the guy that used it (phew, good thing that this is a blog). And what is even scarier is that after a few years we'll start seeing movies about the Muslim Holocaust in Guantanamo. And if they follow the same pattern, we'll never stop seeing them. Man, that would really suck!

Wednesday 17 May 2006

Monday 15 May 2006

Internet Explorer and the hidden table cells.

All the rows in an HTML table have a property called rowIndex, which is the actual index in the rows array. Table cells are in a similar situation with their property cellIndex. BUT, Internet Explorer chooses to interpret cellIndex as the VISIBLE index, rather than the internal one. Netscape, Mozilla and Opera do not exibit this behaviour. Funny thing, the rowIndex works in IE no matter how you hide the rows.

More detailed, style.display='none' makes the cellIndex of the next cells to decrement, while style.visibility='hidden' does not decrement the cellIndex, but keeps the formatting of the page, so you actually see a big empty space where the cell used to be.

I wouldn't have mind this if the Microsoft guys used another index to show the internal value, but they didn't! I have no idea what is the internal index of my cells anymore! Grrr!

Difference between NEW and OVERRIDE in .NET.

Except the obvious one that override cannot be used on methods not declared as virtual, there is the little nag of how the original object will use the method internally. Mainly it will use its own not overriden code, but not the methods that hide its code.

Object A has a method M virtual. B inherits A and overrides method M.
With an instance of B, B.M() will run the code in object B, while M() inside the code of object A will also run the code in object B.

Object A has a method M not virtual. B inherits A and hides method M with a new M method.
With an instance of B, B.M() will run the code in object B, while M() inside the code of object A will run the code originally in object A.

Ex:

public class PrintStuff
{
public PrintStuff() {
PrintMe();
}

public void PrintMe() {
Console.Write('ME!');
}
}

public class PrintStuff2: PrintStuff
{

public new void PrintMe() {
Console.Write('new ME!');
}
}

a code like new PrintStuff2(); will output ME! while a code like new PrintStuff2().PrintMe() will output new ME!

Thursday 11 May 2006

Policy not being applied to reference at this time error from hell

I've always compiled and tested web applications on the company server, but then I found myself in need of debugging so I started a project on the local machine. Then I started to get random errors when compiling the code.

===Errors from hell===
Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: Access is denied: 'Some.DLL.Library'.

Source Error:


Line 196: <add assembly="System.EnterpriseServices, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
Line 197: <add assembly="System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
Line 198: <add assembly="*"/>
Line 199: </assemblies>
Line 200: </compilation>


Source File: c:\windows\microsoft.net\framework\v1.1.4322\Config\machine.config Line: 198

Assembly Load Trace: The following information can be helpful to determine why the assembly 'Some.DLL.Library' could not be loaded.


=== Pre-bind state information ===
LOG: DisplayName = Some.DLL.Library
(Partial)
LOG: Appbase = file:///c:/inetpub/wwwroot/WebAppFolder
LOG: Initial PrivatePath = bin
Calling assembly : (Unknown).
===

LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Post-policy reference: Some.DLL.Library
===Errors from hell===

Do you want to know what was wrong? The Indexing Service rings any bell?

PRB: Access Denied Error When You Make Code Modifications with Index Services Running

Wednesday 10 May 2006

Passing arguments to Custom Actions in Visual Studio Setup Projects

Among my most disgusting duties is creating setup projects, mostly with Visual Studio. One thing I've stumbled upon is the way to pass arguments to Custom Actions.

Imagine you want to add parameters containing spaces like:
/dir "[ProgramFiles]" /dir2 "[MyDocuments]"
In the custom action arguments box write this:
/dir "[ProgramFiles]\" /dir2 "[MyDocuments]

That's the only way I could make it work. I still don't have any idea why.
So if you want to have a parameter with spaces in it, add a quot in front of it, but don't add one at the end. If you need to have other parameters after this one, end the quot block with backslash+quot.

Update:
Apparently, Windows Vista and its MSI engine doesn't support custom actions anymore. If you want to make your setup projects "worthy" of Vista, you should avoid using custom action.

Looping through Javascript object properties

Update July 2016: This post is really old and obsolete. In it I was describing getting both attributes of DOM elements and properties of the element object, a thing that should rarely be useful. Even so, I will update the post with the better way of doing this.

First of all, looping through the properties of a Javascript object:
// for ... in ...
for (var key in obj) {
console.log(key,obj[key]);
}

// using Object.keys (IE9+) and a normal for loop
var keys=Object.keys(obj);
for (var i=0; i<keys.length; i++) {
var key=keys[i];
console.log(key,obj[key]);
}

// using the Array.prototype.forEach function (IE9+)
Object.keys(obj).forEach(function(key) {
console.log(key,obj[key]);
});

// for ... of ... from the new ES6 specification
for (var key of Object.keys(obj)) {
console.log(key,obj[key]);
}

All of the methods above are similar, but not exactly the same. For example, the for...in loop goes over all the properties of an object, including those coming from its prototype. Object.keys (the other three methods, which all basically iterate over an array) only takes the set properties of the object itself. One can determine if an object has the property or it comes from the prototype using Object.prototype.hasOwnProperty and can determine if the object has a property of any kind using
var hasProperty = (typeof obj[key] != 'undefined')
or the relatively more recent
var hasProperty = (obj[key] !== undefined)
I say relatively more recent because in some browsers the value of undefined could be set. (Note the strict inequality sign, because undefined==null, but undefined!==null).

Now that we went through methods of iterating over the elements of arrays, it's trivial to enumerate the HTML attributes of an element, because they are stored in an attributes NamedNodeMap, which even if it looks like an array, with a length property and numeric indexes, it is not. forEach doesn't work, for example.

for (var i=0; i<obj.attributes.length; i++) {
var attr=obj.attributes[i];
console.log({
index:i,
name:attr.nodeName,
value:attr.nodeValue
});
}

Note that console.log(attr) will return a string like representation of the object because for some reason attributes have a valueOf overload that turns them into a string like key="value". You can also transform the NamedNodeMap into an array using Array.from (not in IE or Opera!) then use forEach, if that's your thing.

And below is the 2006 post... yuck!

I've always needed to read the attributes of objects in Javascript for my
custom controls. Imagine a tag like this:
<span id=test1 attribute1="value">
followed by a Javascript code like this:
test1.attribute2="anotherValue";

There are two solutions for reading the attributes of an object:
1. for-in loop:
for (var name in test1) alert(name+':'+test1[name]);
2. use the attributes property (the W3C DOM way)
for (var c=0; c<test1.attributes.length; c++) {
var attr=test1.attributes[c];
alert(attr.name+':'+attr.value);
}
Or, if you are fortunate enough to know the attribute name, you can use
obj.setAttribute(name,value);
value=obj.getAttribute(name);

How nice. Now the good part, these pieces of code work differently for IE
and non IE browsers. What a surprise.
IE:
- both loops show all the properties of an object, including methods,
attributes specified in JS code or in html tags. The functions specified in
a tag are returned as [object]s.
- also setAttribute and getAttribute work the same, returning object
properties or tag attributes
FireFox, Opera and Netscape:
- the for-in loop returns only the object properties and methods, NOT the
things defined in the HTML tag
- the attributes loop returns ONLY the tag attributes
- getAttribute will only return the tag attribute while setAttribute will
change only the attributes, not the object model
- in the case that a tag attribute is automatically transformed by the
browser in an object property (like an event onchange="test();")
obj.onchange will return a function object, while
obj.getAttribute('onchange') will return a string

Therefore the only way I found to loop through all the properties of both
html tag and DOM object is by using both loops. ex:
function PassAttr(elem1,elem2) {
for (var c=0; c<elem1.attributes.length; c++) {
var attr=elem1.attributes[c];
if (attr.name.substring(0,5)=='list_')
elem2.setAttribute(attr.name.substring(5),attr.value);
}
for (name in elem1)
if (name.substring(0,5)=='list_')
elem2.setAttribute(name.substring(5),elem1[name]);
}

Saturday 6 May 2006

Religion Sucks

Ok, non IT post (rambling) about religion. Episode two from The World Sucks internationally renowned series.
Religion sucks! I mean, not only that they advertise a two thousand year old fairy tale, but they do it agressively, violently and with no taste whatsoever. And I am not even talking about stupid people blowing themselves up because some other guy told them a deity said so. I am talking about Christians. Yes, the religion of the one God who must use hidden adverts to get more followers to donate to churches all over the place, as I like to call it.

I was searching for online adventures, as my favourite game site has been down for a few days and I found this fairy tale made in flash, with things to uncover, hidden alphabets, complex storyline. I like this kind of games, so I started playing it. In no time I realized that the hidden messages were not useful in the game, but rather poetic allegories to something. Then, when I needed to fight the evil dragon, the only solution was to abandon all my weapons and face him, while a SHEPPERD was fighting the dragon and DYING FOR ME. Later I find that the shepperd has been a KING that death CANNOT HOLD. Guessed it yet? Yeees. Congratulations for winning this absurdity of a game, let the dragon consume you and join our idiotic church! The next game in the google search had a similar purpose.

Of course, this is just an example of why religion sucks, and one might argue that the moral values advertised by most religions are more important than a few zeleous spammers and their annoying actions. You might even have a point, and as there is no way to prove a god exists or not, there is no way to disprove its existence as well. Therefore I submit my point of view: the dragon is real, he takes care of us by bitting the head of dumbass religion freaks, hates spammers and burns any god to a crisp with his firey breath. What? You don't believe me? Do you have any proof that HE doesn't exist? I mean, there are a lot of freaks out there who lost their head over religion and I haven't seen any of your gods doing anything of value lately. And of course the dragon hates spammers, everyone does!

Religion sucks! It's my firm religious belief. And I have 65100 Google followers.

Tuesday 2 May 2006

Global.asax and Session_OnEnd

Global.asax and Session_OnEnd

You may have already used it, but I just found out about it. There is a
global.asax file in each web project, it contains a lot of events that one
can use, like Application and Session start and end events.

Now, I tried to make Session_OnEnd to work well for the last hour, the trick
is follow these rules:
1. The session must be in InProc mode
2. In the Session_OnEnd (and Application_OnEnd) you cannot use Server,
Response or Request objects. So Map.Server will fail, for example. Also,
throwing exceptions will not cause any display on the actual page or new
pages, they just go unnoticed. This also means HttpContext.Current doesn'
work.

That is it. The Session_OnEnd event will fire on:
1. Session.Abandon
2. session timeout

Weirdest javascript Date daylight savings bug

FINAL UPDATE: I have tried this today, 7th of May 2008, and the bug is gone from all versions of IE and FF. I think it is the result of some Windows XP patch.

I found out that in Javascript, the Date object can give weird results.
Imagine that new Date(2005,2,27) [Javascript months are 0=11] returns 26 March 2005. If you look closely, you will see that it returns 26.03.2005 23:00:00.
Why? Because then our computers are configured to change the time with one hour. In a sense, this is not an error, as 27.03.2005 00:00:00 does not exist. You either have 1:00 of the 27th or 23:00 of the 26th. It is weird that Javascript both on IE and Netscape (and probably all other browsers) chooses the second option.

[Update thanks to a comment]I live in Romania. 27 of March 2005 is a daylight saving date (a bit non standard). Maybe the same bug can be reproduced for other countries on their respective daylight saving dates.[/Update]

This can yield weird results, as validators sometimes fail to recognize 27.03.2005 as a valid date. The solution for Javascript code: always use new Date(year, month, day, 12, 0, 0). The solution for validators... well, except calling Microsoft and bitching about it or changing the validator JS
file on ALL deployment servers, is either use a home made validator or replace the faulty validator js function in the pages that need date validation.

That means adding in the common site js this function:

function ValidatorConvert(op, dataType, val) {
function GetFullYear(year) {
return (year + parseInt(val.century)) - ((year < val.cutoffyear) ? 0 : 100);
}
var num, cleanInput, m, exp;
if (dataType == "Integer") {
exp = /^\s*[-\+]?\d+\s*$/;
if (op.match(exp) == null)
return null;
num = parseInt(op, 10);
return (isNaN(num) ? null : num);
}
else if(dataType == "Double") {
exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + val.decimalchar + "(\\d+))?\\s*$");
m = op.match(exp);
if (m == null)
return null;
cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
num = parseFloat(cleanInput);
return (isNaN(num) ? null : num);
}
else if (dataType == "Currency") {
exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + val.groupchar + ")*)(\\d+)"
+ ((val.digits > 0) ? "(\\" + val.decimalchar + "(\\d{1," + val.digits + "}))?" : "")
+ "\\s*$");
m = op.match(exp);
if (m == null)
return null;
var intermed = m[2] + m[5] ;
cleanInput = m[1] + intermed.replace(new RegExp("(\\" + val.groupchar + ")", "g"), "") + ((val.digits > 0) ? "." + m[7] : 0);
num = parseFloat(cleanInput);
return (isNaN(num) ? null : num);
}
else if (dataType == "Date") {
var yearFirstExp = new RegExp("^\\s*((\\d{4})|(\\d{2}))([-/]|\\. ?)(\\d{1,2})\\4(\\d{1,2})\\s*$");
m = op.match(yearFirstExp);
var day, month, year;
if (m != null && (m[2].length == 4 || val.dateorder == "ymd")) {
day = m[6];
month = m[5];
year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3],10))
}
else {
if (val.dateorder == "ymd"){
return null;
}
var yearLastExp = new RegExp("^\\s*(\\d{1,2})([-/]|\\. ?)(\\d{1,2})\\2((\\d{4})|(\\d{2}))\\s*$");
m = op.match(yearLastExp);
if (m == null) {
return null;
}
if (val.dateorder == "mdy") {
day = m[3];
month = m[1];
}
else {
day = m[1];
month = m[3];
}
year = (m[5].length == 4) ? m[5] : GetFullYear(parseInt(m[6], 10))
}
month -= 1;
var date = new Date(year, month, day,12,0,0); //BUG FIX
return (typeof(date) == "object" && year == date.getFullYear() && month == date.getMonth() && day == date.getDate()) ? date.valueOf() : null;
}
else {
return op.toString();
}
}

Resharper 2.0

I've just installed Resharper 2.0. It still has little bugs, but it has that system where you can remember and ignore a set of errors.

What can I say? It's a the greatest software tool EVER. It can generate code, complete code, suggest changes, basically what Resharper 1.5 did, but
now it's WAY better.

The best thing in 2.0 I think it's Live Templates. They work like macros, but from just a few key presses and are way easy to configure. Imagine you
want to do something like :

throw new Exception("Any message");

all you have to do is type thr[Tab] and you get

throw new Exception(""); and the cursor between the quotes.

Of course that means also: itterating through a dictionary, creating for loops, transforming types into other types, automatic creation of aspx code
like datagrid columns, etc.

You want to put a piece of code in an if block, a region or a try catch, just select the code , press ctrl-alt-J and choose the type of block.
You want to add the properties and methods of an object inside your class to your class, just press Alt-Insert and choose the object and the members and you have them all in your class, referenced to the internal object and commented!

The Live Template system includes a scope of the template. That means that the template for creating a new method will not work inside a method, or
aspx code will not be generated into a cs file, etc.

Other two nice tools that I've found are :

- CommentReFlower - which takes care of the comments in your code. Not terribly useful, but time saving when you need to comment code
- RegionsAddIn - it allows you to take pieces of code and move them into regions, or create new ones.

Both are addins for visual studio 2003.

How to stop an object from being garbage collected

You go to the MSDN site and you get this as a proper implementation of the IDisposable interface:

#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
// Check to see if Dispose has already been called.
if (!_isDisposed)
{
_isDisposed=true; //this is what I added, I think it makes this thread safe
if (isDisposing)
{
//Clean up resources
}
}
_isDisposed = true;
}
#endregion

In other words, implement IDisposable to clean up unmanaged resources. Well, unmanaged could be considered managed code from another thread. If your object starts a thread that calls an event, then when you exit the code block where you declared the object, then the event will never get fired. A pending action is unmanaged, therefore you can do something like:

while (!actionFinished) Thread.Sleep(1000);

the action should, of course, set actionFinished to true;

The AS keyword in C# or Safe Casting

If you have ever used code like:
try {
obj1=(TypeObj1)obj2;
} catch {
obj1=null;
}

you need to read this.

The same thing can be written as:
obj1=obj2 as TypeObj1;

In case the conversion doesn't work, the value of obj1 will be null.
Be careful when you do this with value types that don't allow null.

Update:
Also, implicit casting will not work. A code like:
int i=5;
string s=i as string;

will have s being null, not "5".

You also have to be careful about using the "is" word. Code like
if (ctrl is Table) {
Table tbl=(Table)ctrl;
tbl...

actually casts ctrl twice!
a is b translates to (a as b)!=null.

So a nice piece of code would look like this:
Table tbl=ctrl as Table;
if (tbl!=null) {
tbl...

The 'implicit' operator in C#

Did you know that in a class you can do something like:
public static implicit operator type2(type1 value) {
return value.ToType2();
}


Now class type1 will be automatically converted into type2 when used as such.

Example:

public class NullBoolean {
private bool internalBool;

public static NullBoolean False {
return new NullBoolean(false);
}

public static NullBoolean True {
return new NullBoolean(true);
}
public NullBoolean(bool value) {
internalBool=value;
}

public static implicit operator bool(NullBoolean) {
return internalBool;
}
}


with this class all these statements are correct:
NullBoolean nb=null;
nb=NullBoolean.True;
if (nb==true) MessageBox.Show("nb is true"); // no cast

if the word implicit would have been explicit, then the compiler would have required you to cast nb to bool first:

if ((bool)nb==true)...


Add to this Equals, ToString and == overide and you have a nice boolean type that allows for null values.

Update:
First of all implicit operators are a kind of a shortcut for casting. Sometimes this doesn't work, like in foreach loops. Sometimes a code like this will not work:
foreach (RowAdapter ra in dt.Rows) ...

while this would work:
foreach (DataRow dr in dt.Rows) {
RowAdapter ra=dt;...

Second of all, an object like the one above can in NET 2.0 be easily formed with nullable types:
bool? nb;

Windows Management Instrumentation (WMI)

Windows Management Instrumentation (WMI) provides access to information about objects in a managed environment. Through WMI and the WMI application programming interface (API), applications can query for and make changes to static information in the Common Information Model (CIM) repository and dynamic information maintained by the various types of providers.

What that actually means it that one can get information about the computer and operating system or subscribe to global events. I've already added a
SystemManagement object to the Siderite library, but it is only a wrapper for a few lines of code that are easy to do anyway.

Cool things that WMI can help you with:
- Enumerate harddrives, networkcards, PCI slots, operating system information, processors, processes, registry keys, security policies, windows start menu items, etc. and their properties (physical memory size, processor ID, etc)
- Subscribe to events like "a specific registry key has been changed" or "a new process started/ended" or "windows is shutting down".

It is also interesting that this can be done to a remote system as well, just like the Windows Task Manager which uses WMI to get and display all information and can connect to another computer.

It seems that the NET framework comes with some nice command line utilities. One of them is MgmtClassGen.exe.

Basically what you do is:
MgmtClassGen.exe /P
And it creates a strong typed wrapper for the WMI class.

Example:
MgmtClassGen Win32_Processor /P processor.cs
creates a Processor class that controls everything about the processor.

For a complete list of WMI classes check out:
Computer System Hardware Classes

Customizing Dialog Windows

I had to do this Export functionality that saves data in a file from the database after filtering by date. My first idea was "let's just export everything and only use an OpenFileDialog", but then the date filtering request came. I thought that changing the OpenFileDialog to add two date
time pickers would be an easy job, but, alas, it is close to impossible.

Good research came out of this, though:
FileDialogExtender - Customize a dialog by issuing API Messages to already open windows
Customize Your Open File Dialog - Customize a dialog by changing the registry
Advanced MessageBoxing with the C# MessageBoxIndirect Wrapper - a friendly C# wrapper class for the MessageBoxIndirect API that allows you to add a help button, custom icon, locale-aware buttons, and different modalities to a message box.
Control.WndProc Method - MSDN WndProc method

How to access private members and methods

You use the InvokeMember function.

Quick example:
typeof(DataGrid).InvokeMember("RowAutoResize",BindingFlags.InvokeMethod|BindingFlags.NonPublic|BindingFlags.Instance,null,wDataGrid1,new object[] {1});

This is equivalent to wDataGrid1.RowAutoResize(1), which would not normally work because the method is private.

The syntax for InvokeMember is:
public object InvokeMember(
string name, // name of the method
BindingFlags invokeAttr, // Binding flags, see below
Binder binder, // Use null for the default binder. A Binder object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection
object target, // object that owns the method you want to run
object[] args // argument array
);

Why does it work? Because access-modifier based security has no impact on Reflection
Ok, some of you might ask themselves How do I protect my code in libraries and other things I publish? Add this in front of the namespace declaration:

[assembly:ReflectionPermissionAttribute(SecurityAction.RequestRefuse,
Unrestricted=true)]

By setting the ReflectionPermission to RequestRefuse at assembly level, you could prevent all the accesses to private members and if someone tries to access it, it throws 'System.NullReferenceException'. In the above example, at fInfo.SetValue it throws NullReferenceException, because it is able to create fInfo object.


I think this is a greatly useful feature, especially when working with
Microsoft objects that have a lot of nifty procedures all marked with
private or internal or both :)

Controls created on one thread cannot be parented to a control on a different thread error.

Trying to build a reusable object that is independent of the Windows or Web interface I've stumbled upon the issue of multiple threads trying to access and modify the same form. The ugly "Controls created on one thread cannot be parented to a control on a different thread." error occured and, no matter what I tried, it seemed it will never work. But finally I found out the solution.

First the issue:
doing something on the interface was starting a separate process that ran an external program. The interface has a progress bar that was updated during this. At the end of the process, an event was fired, and to that event I added a method that was supposed to clear the progress bar and put another UserControl on the form. The the error occured.

The problem was that the event was fired by the separate process that ran the external program. Trying to change something in the form that was created on another thread resulted in error.
The solution is that inside the method called by the event any references to methods that change the interface must be done through BeginInvoke:

private delegate void MethodDelegate(int i)

private void TestMethod(int i) {
// change interface here
}

private void OnEvent(object sender, EventArgs e) {
<interface_form_object>.BeginInvoke(new MethodDelegate(TestMethod),new
object[] {i});
// this replaces using TestMethod(i) which generates an error
}

Update on this:
Use the BackgroundWorker class in NET 2.0.

Bootstrapper for the Visual Studio .NET Setup Projects installs the NET framework automatically

Using Visual Studio .NET 2003 to Redistribute the .NET Framework

It is as easy as downloading the Bootstrapper .MSI file and running it. Next
time you compile a Setup project it will include the dotnetfx.exe file and
the code required to install it on demand.

Another great tool is found here: RyanVM's MSFN Files Page
It is a switchless .NET installer. Just run it (as a custom action, for
example) and it will insure that you have .NET framework installed, no
questions asked.

ASP.NET HTML Rendering

One of the major marketing statements regarding ASP.NET was its capability to display content differently depending on browser. What actually happends, though, is that Internet Explorer is considered a HTML 4.0 compatible browser, while others are not. If you ever looked at a normal page with a few textboxes and a button on Firefox or Netscape, then you know what I mean.

Example:rendering for FireFox:

<table width="30%" border="2">
<tr>
<td align="Right">
<span >
Hi there...
</span>
</td>
</tr>
</table>


rendering for IE:

<table width="30%" border="2">
<tbody><tr>
<td style="FONT-SIZE: large; COLOR: red" align="right">
Hi there...
</td>
</tr>
</tbody></table>


In this case, if you want to , let's say, replace the innerHTML property of the td, then you lose the color red.Other such changes put the width/height parameters inside the style property or outside it.

Apparently, the difference in rendering comes from the HtmlTextWriter class. For "not compatible browsers" an overridden class is used for rendering: Html32TextWriter.

How to fix it.
The recomended fix for this is change the tag in machine.config. That would make your server compatible to each browser as you see fit. The downside of this, of course, is that your ASP.NET application will render differently for each hosting server making it undeployable.

My fix.
Just inherit the Page class and add this:
protected override void Render(HtmlTextWriter writer)
{
writer=new HtmlTextWriter(writer.InnerWriter);
base.Render (writer); // or your own rendering logic
}
and use this page class for all forms.

This will make all controls on the page render for HTML4.0 compatible browsers. In my personal opinion, we will never make sites that are designed to be seen with Internet Explorer 3.2 or Nescape 4 so this will work. Of course, that doesn't make the pages look the same on all browsers. One needs to check out all the details regarding browser compatibilty such as the way the Visual Studio IDE adds or removes DOM incompatible attributes, but it's a major step forwards.