Archive

Archive for the ‘.NET 2.0’ Category

Event Handling made easy

July 11, 2007 Comments off

UPDATE NOTICE: This approach has been updated to take advantage of the EventHandler<T> generic delegate. The updated approach is covered in Event Handling made even easier.


If you have been around .NET for a while, you have probably already discovered Events and may be confident in their application. For me, it is something that I inherently understand but have not used enough to remember all the pieces from scratch. As a result, every time I find a situation that I think calls for Event Handling, I have to relearn the physical process of it from scratch. So I decided to write this little tutorial so I would always have it laid out for myself in one place.

Why Events are so Cool

Events have some really cool benefits. First of all, they can be wired into any object. This lets any object report information about itself. Secondly, the events can be monitored or ignored – it is up to other objects to listen or not. The uses of this are pretty much infinite, but I’ll lay out two that I think will make sense for just about all of us.

State Reporting – Imagine a class that encapsulates a record in a database. Now imagine you have a method that reports whether or not the data is “dirty” (meaning that some data has changed and needs to be updated to the database). In order to make use of this information, you need to run the CheckForIsDirty method whenever the object may have changed. This could be a lot of calls to the same method, and could easily be missed in your code. Events offer us another approach. If the object did the checking itself (say in the Set property for each data element) it could fire an IsDirtyChangedEvent whenever the state changes from true to false or vice-versa. Now in the object that needs the information – say to set the Enabled state of a Save button – you simply wire up a single event handling method to the object.

Error Reporting – Similarly, you could use an Event to report errors, rather than the typical Exceptions being thrown and caught. For one thing, while Exception handling is robust, it is also kind of a pain. In order to do it well, you should handle every Exception that could be thrown. This is tedious and the Exception code you write is rarely used. Consider also that a lot of us (myself included) get lazy with Exceptions and just use a standard catch (System.Exception ex) style catch block. This of course defeats the purpose of the robust exception handling offered by .NET. But in those cases, what we really want to know is if any error occurred at all. But the worst of all is when the unexpected exception occurs… you know, the one you don’t plan for that never shows up in testing but that the user seems to find no problem.

So now, let’s consider the same object from above, an encapsulating database record object. Potentially, we could have all kinds of errors caused by invalid data. Simple issues like code-driven fields or too many decimal places, etc. etc. Or it could even be a complex issue with multiple fields having different rules based on the values of other fields. Do you really want to throw (and therefore need to catch) every possible Exception? Sometimes yes, sometimes no. If you are looking for a simple “catch-all” (forgive the pun please) error reporting system, you could create a simple MyObjectErrorOccurredEvent. Throw this event where ever you would have thrown an Exception. Again, in your parent object, you can define a single method to handle all the errors.

These are just a couple examples of things you can do. In the Sketching tool I wrote about recently, I used an Event to notify the parent when each sketch had been created. The parent then updated a counter and reported the progress back through a delegate to the GUI thread. Very slick, and fairly easy.

Enough already, how do I do it?

Fair enough. This is my simple method of doing Events. There are five steps, which I’ll outline in order.

Step 1: Outside of any Class, create a public delegate to define the EventHandler signature.

public delegate void IsDirtyChangedEventHandler(object sender, IsDirtyChangedEventArgs e);

The (object sender, xxxEventArgs e) signature ought to be very familiar to you. This is the basic signature you get for every button_pressed, on_click, mouse_up, etc. etc. event. In our case, we have a custom xxxEventArgs class that we are going to create. Feel free to replace this with any of the standard EventArgs, so long as they will suit your purpose. I find that they usually don’t so creating our own is the way to go.

Step 2: Create our custom EventHandler class. Again, this is optional if you choose a standard EventArgs class. This class is very simple, just a collection of values, really. In our case, it is just going to be one value: a boolean representing whether or not the object IsDirty.

public class IsDirtyChangedEventArgs
{
    private bool _isDirty;

    private IsDirtyChangedEventArgs()
    {
    }

    public IsDirtyChangedEventArgs(bool isDirty)
    {
        _isDirty = isDirty;
    }

    public bool IsDirty
    {
        get { return _isDirty; }
    }
}

Step 3: In the class that is firing the Event, we need to define the event so that other objects can handle the event.

public event IsDirtyChangedEventHandler IsDirtyChangedEvent;

Note that while the Type is a IsDirtyChangedEventHandler, we traditionally leave Handler off the name.

Step 4: Fire the Event. This is pretty straight-forward: when ever you reach the right place in your code, fire the event.

public bool IsDirty
{
    get
    {
        return _isDirty;
    }
    private set
    {
        if (_isDirty != value)
        {
            if (IsDirtyChangedEvent != null)
            {
                IsDirtyChangedEvent(this, new IsDirtyChangedEventArgs(value));
            }
        }
        _isDirty = value;
    }
}

In this case, I have used a private Set property to set the internal variable. Before I update it, I see whether or not it has changed, and if it has then I Fire the event. This way (as long as I always set it using the Property and not accessing the variable itself), the notification is always sent out regardless of what triggered the change. Note that we check to see if the Event is NULL prior to attempting to fire it. If there is no method registered to handle the event, the Event call itself will result in a NullReferenceException.

Notice that I have also employed our custom IsDirtyChangedEventArgs class when I fired the event. If the EventArgs object was any more complicated, I would probably have put it on its own line first.

Step 5: Wire the event up in the parent. Now that I have the Event defined and firing, all I need to do now is add a listener to capture the event in my parent object. There are two parts to this: first you have to register the Event listener with the object.

MyObj _myObj = new MyObj();
_myObj.IsDirtyChangedEvent += new IsDirtyChangedEventHandler(_myObj_IsDirtyChangedEvent);

Of course, VisualStudio and Intellisense will write most of this very ugly signature for you. Even better, once created it will allow you to press TAB and it will create part 2, the actually handler event.

private void _myObj_IsDirtyChangedEvent(object sender, IsDirtyChangedEventArgs e)
{
    this.SetSaveButton(e.IsDirty);
}

As you can see, I have added the code I want to execute whenever the change event is fired.

Conclusions

And that is my simple Event handling method. They really are quite simple, and the sky’s the limit as far as their usefulness goes. So if you haven’t done it before, do it now! If you have done some Events, feel free to comment on my methods above.

Categories: .NET 2.0, C# 2.0

PolygonF and Polygon code posted.

June 26, 2007 Comments off

I have just posted the PolygonF code I discussed in Testing to see if a Point is within a Polygon. The file includes both PolygonF and Polygon classes. Visit the Free Code page or download it from the PolygonF home page.

Categories: .NET 2.0, C# 2.0

Testing to see if a Point is within a Polygon

June 7, 2007 8 comments

I’m on a brief respite from my Compact Framework woes: I am instead in the process of rewriting a very old Java Sketching program. Our legacy application stores text-based vectors for drawing 2D sketches of the external footprint of structures. Until I wrote this Java program in 2001, our sketches were always rendered in Text. Yes, I said TEXT. Dashes, underlines, plus signs, forward slashes and backward slashes – well you get the idea. We began displaying some of this information on the Internet and needed something a little more modern. This program in particular reads through our entire database and creates all the Sketches as JPGs, storing them locally on the C drive. There is a companion program that creates and displays in a GUI a single sketch requested by the user (via a function key in our iSeries RPG program).

In fact, one interesting note about it: this was the first PC based program I ever wrote. Since I was in the throes of learning Java anyway (my first PC or Web related language), I took on the task of making something out of nothing. Of course, I had no idea what I was getting in to, but I ended up with a crash course in Object Oriented design, JDBC and disconnected databases, Swing (shoot me if I ever go down THAT path again!), and of course 2D graphics. For someone who did not know the first thing about GUI development, this project was way too much for a first try. But 5-6 months of reading, studying, trial and error, and labor and I ended up with a workable program.

Don’t get me wrong: it is an abhorrent behometh, chock full of bad techniques and poor implementations. Worst of all, it is a Java program, and on more than one occasion has broken due to updates in the JRE. Couple that with the fact that it is slow as death (again, certainly my own fault) and almost NEVER deploys properly thanks to myriad Classpath woes and divergent operating system. After my last machine bit the dust, I never even bothered to recreate my Java environment (as I had completely moved on to VS2003 by then). As a result, legitimate complaints by users have gone unaddressed, largely because of my own unwillingness to return to Java.

Fast forward to today: now experienced in Java, PHP, Perl, and of course my favorite, C#, and having done quite a bit of GUI and OO development in the intervening years, I finally decided to tackle the rewrite of my old behometh. I rewrote the engine Wednesday afternoon, and by the end of the day had rudimentary sketching working. 5 Hours to do what originally took 5 months. I spent part of yesterday working on the Text labelling, which is quite a bit more difficult than the actual drawing. I’ll probably spend another few days hashing all that out.

During my labors, though, I discovered a shocking omission in the C# language: there is no Polygon Class. Drawing the Polygons is easy enough using the Graphics DrawPolygon member, but as I am inserting labels, I need to check and see if the proposed position is within the Bounds of the Polygon, and I would like to center some labels, so I need to know what the center point is, etc., etc. So, I quickly whipped up my own Polygon class. The class manages a read-only Array of PointF objects, so right now it is immutable. I may change that if the need arises, but for now I need to work with the complete closed Polygon.

It is not overly complex or anything like that, but here are some of the key features

  • Bounds of the Polygon
  • CenterPoint of those Bounds
  • Minimum and Maximum X and Y
  • Number of Points
  • Determine if a PointF is in the Bounds
  • Calculate Area of the Polygon
  • Determine if the Polygon Contains a PointF (different than above)

That last one was a real challenge. A PointF could easily be in the Rectangular Bounds of a Polygon but not inside the Polygon itself, so the Contains check determines whether or not the PointF is actually inside the boundaries of the Polygon. This required more math than I was able to come up with, so I turned to my trusty friend Google and found this link. At this site, you can find the formula originally written in Fortran and converted to C. Naturally, I converted it on to C#, and I am now sharing that code with you.

public bool Contains(PointF pt)
{
    bool isIn = false;
    if (IsInBounds(pt))
    {
        int i, j = 0;
        for (i = 0, j = NumberOfPoints - 1; i < NumberOfPoints; j = i++)
        {
            if (
                (
                 ((_pts[i].Y <= pt.Y) && (pt.Y < _pts[j].Y)) || ((_pts[j].Y <= pt.Y) && (pt.Y < _pts[i].Y))
                ) &&
                (pt.X < (_pts[j].X - _pts[i].X) * (pt.Y - _pts[i].Y) / (_pts[j].Y - _pts[i].Y) + _pts[i].X)
               )
            {
                isIn = !isIn;
            }
        }
    }
    return isIn;
}

You can see that I bypass any points that are outside the rectangular bounds altogether since there is no point in running the rest of the checks at that point, but that is really the only fundamental change I made. Of course, I return an actual Boolean but the orginial C returned an int.

When I complete the rest of the Polygon code, I’ll post it in the Free Code section. This one is actually PolygonF for using floats, but it could easily be modified to use Integers instead.

UPDATE:

Download PolygonF.

Categories: .NET 2.0, C# 2.0

IBM iSeries .NET Managed Provider

May 14, 2007 1 comment

I have long been a fan of IBM’s midrange server family, whether you want to call it the AS/400, the iSeries, the i5, or the IBM name du jour. Above all else, having the operating system, the hardware, and the database (UDB DB2 for iSeries) is the best thing about the box. My .NET specialty has really become using .NET to communicate with the iSeries. I have been taking advantage of the IBM supplied managed provider, which works great.

EXCEPT: last year, when I switched over to .NET 2.0, I started getting a strange message:

System.ObjectDisposedException was unhandled
Message=”Safe handle has been closed”
Source=”mscorlib”
ObjectName=””
StackTrace:
at System.Runtime.InteropServices.SafeHandle.DangerousRelease()
at System.Threading.RegisteredWaitHandleSafe.Finalize()

This happens on ANY and EVERY program that opens a Connection object to the iSeries server. It took a little while to track down, because the message is never thrown in conjunction with any of the windows code. I even tried using the Debug Exceptions option and set it to stop when the ObjectDisposedException was thrown, but still no joy. Eventually, through trial and error, I was able to determine that it was coming from the IBM.Data.DB2.iSeries code itself. With not much to do about it, and lots of other coding to get done, I carried on knowing in the back of my head that eventually I would have to fix it.

Well, eventually arrived last week. The PC side of my current project went to beta testing last week with the error intact. Needless to say, it quickly made it to my short list of “fix now” type problems. So I’ve done some more research and found the following.

DESCRIPTION OF PROBLEM FIXED FOR APAR SE22506 :
-----------------------------------------------
   When using the IBM.Data.DB2.iSeries .NET provider with
   .NET Framework 2.0, an ObjectDisposedException occurs
   when the application terminates, with a message indicating
   "Safe handle has been closed."  This problem occurs
   because of an incompatible change made in the .NET
   Framework.

CORRECTION FOR APAR SE22506 :
-----------------------------
   This ptf fixes the reported problem.  Note that this is not an
   official support statement for .NET Framework 2.0.  Future
   compatability with .NET Framework 2.0 is not guaranteed.

CIRCUMVENTION FOR APAR SE22506 :
--------------------------------
   None.

Oooooo-KAY. Did I read that right? “This problem occurs because of an incompatible change made in the .NET Framework” IBM says the problem is with the Framework, but isn’t the responsibility of the Managed Provider PROVIDER to meet the requirements of the Framework? It’s kind of like Congress saying it’s law making is defective because of the Constitution. Ummm… isn’t that the document that tells YOU how to make the laws?

OH… and I just LOVE this: “Future Compatibility with the .NET Framework is not guaranteed.” Then what is the point of the stinkin’ Provider? I know I know, they are just giving themselves an out. They can’t appear to officially support anything Microsoft does.

This is just more evidence of why I love the IBM machinery, but am not so fond of IBM itself.

BTW, for those looking for the fix, you need to apply the PTF available at the above link. Following the “Supercede Available” links will eventually land you at SI26600. And it is for V5R3, so if you are on an earlier release (like me) … sorry …

UPDATED POST HERE

Categories: .NET 2.0

Using the KnownColor Enum

May 4, 2007 1 comment

DOWNLOAD THE CODE

I was recently searching for a color to use as a warning color for one of my apps. Basically, when the user entered a particular state in the application, I wanted to change the background of a panel to something unusual so they would immediately see that something had changed. While I ended up using standard Color.Red, I don’t really like it (and it washes out something onthe panel that is already red). So I was looking through the named colors in Visual Studio, and more than a little frustrated that I didn’t know what some of the colors really were.

So I got to thinking that a it might be handy to have a utility that would let me scroll through the System names and see the colors. So I took a few mintues, spent a little time on the Internet, and popped out a SystemColorChooser. It’s a really simple form:

And if you change one or both of the drop downs, you immediately see the results:

Finding the Magic

The magic in this is the System.Drawing.KnownColor Enum. In it is a list of all the color names you see listed in Visual Studio. I used the code I supplied previously to loop through the Enum and populate the ComboBoxes. I then cast the selected values and used them to set the rightside panel’s color values based on the selections:

private void cboxBackgroundColor_SelectedIndexChanged(object sender, EventArgs e)
{
    this.splitContainer1.Panel2.BackColor = Color.FromKnownColor((KnownColor)Enum.Parse(typeof(KnownColor), this.cboxBackgroundColor.SelectedItem.ToString()));
}

private void cboxTextColor_SelectedIndexChanged(object sender, EventArgs e)
{
    this.splitContainer1.Panel2.ForeColor = Color.FromKnownColor((KnownColor)Enum.Parse(typeof(KnownColor), this.cboxTextColor.SelectedItem.ToString()));
}

Now I have a simple way to select colors based on their System Names.

Categories: .NET 2.0, C# 2.0

Deploying CF .NET 2.0 applications using MSI

January 17, 2007 Comments off

So I’ve been developing Smart Device apps for the last two years, both in VS2003 and now in VS2005. But as the only CF developer in a tiny shop, I have always been able to install them by just using the Deployment option in Visual Studio. Now, however, one of the products I’ve been working on is ready to go to the field for some testing, which means other people have to be able to install it.

Frankly, most of the documentation on deplying CF.NET apps is pretty scary. CAB files, custom INI files, Registry entries, the works. I’ve definitely been spoiled by the MSI features available to Windows forms apps. So I’ve been digging around and experimenting, and I created a CAB file for install and then found the Smart Device CAB project, so I created that but it still required the user to manually copy it over to the device and double click it and yada yada yada. Too much for most of my target audience, and not very professional.

So I dug some more, and I was about to give up, when I found this article on MSDN about using MSI to handle the install to a Smart Device. I went through the article, and after a little trial an error I got it to work. Here are the highlights:

  1. Create your solution and build all the projects. Use Release to keep them as small as possible.
  2. Add a Smart Device CAB project to your solution. Add all your project outputs to the applications folder and add a shortcut to your EXE to the Program Files folder. Build this project.
  3. Add a new Class Library project to your solution. This is an MSI installer helper class that handles events like before_install and after_install. The cool thing is that these events will be found and used automagically later. Fill out the events and build this project. This file has some Registry stuff in it and references a custom INI file that you will need to create, but the forumla is very simple.
  4. Add a new Setup project to your solution. This will be the MSI file that is eventually used to communicate with ActiveSync and install the CF application. By adding custom actions to the installer and referencing the helper DLL we created in step 3, the before and after events will automagically find themselves and fire.

OK, so this is in no way a step by step instruction list. For that, you will want to read the article (like 20 times). It is a little dense but thorough, and I was able to get it to work. I did encounter a permissions problem in the afterInstall event, so I still need to hash that one out, but it did install the app on my device.

One quirk I found was that the article instructs you to add a reference in the MSI project to the System folder and to place your output there for the CABs and the INI file. Unfortunately, this doesn’t jive with the pathing samples in the Helper class code in the article, which references System/TEMP/MyProject. In looking at it, I think the TEMP path is the best way to go, so just create the TEMP/MyProject path in the System special folder and dump your output CAB and INI files there.

Next I’ll be tackling how to integrate CF .NET deployment in the same MSI, so stay tuned.

Finding an Enum value based on its text

January 4, 2007 1 comment

I’ve been a fan of custom Enums since I started coding for .Net: like most software packages, we have tons of selection lists. Many of these are table driven, code-based lists like so:

Code : Description
10 : Asparagus
12 : Carrot
73 : Tomato

etc, etc.

Naturally, I don’t want my users to have to know that 73 means Tomato, so like a good little developer, I put these values into an Enum:

public enum Vegetables
{
    Asparagus = 10,
    Carrot = 12,
    Tomato = 73
}

Then I use that Enum to populate a ComboBox on my Form. To do so, I utilize the Enum class’s GetNames method.

foreach (string s in Enum.GetNames(typeof(MyClass.Vegetables)))
{
    this.cboxVegetableNames.Items.Add(s);
}

The trick here is to point the typeof parameter to the full class designation of the enumeration you want to list. This method returns an IEnumerable you can use to loop through the names.

So far so good: pretty straight forward and probably something most of us have already figured out. The problem I had recently was that I needed the Enum value in order to properly update a database. In other words, when the user selected Tomato, I needed 73. Getting the int value of an enum is easy enough via a simple cast:

MyClass.Vegetables veggie = MyClass.Vegetables.Tomato;
int veggieValue = (int)veggie;

So if I could figure out which Enum value was selected, I could easily get the int. The problem was, I only had the Text string from the ComboBox to go off of. I suppose I could do some sort of brute force loop through all the Enum members until I found a matching string, but that seems like overkill. It would be especially bad if I had lots of options in the ComboBox and lots of ComboBoxes.

Fortunately, I was able to find something a little better built right in to the Enum class:

MyClass.Vegetables veggie = (MyClass.Vegetables)Enum.Parse(typeof(MyClass.Vegetables), this.cboxVegetableNames.SelectedItem.ToString());
int veggieValue = (int)veggie;

It’s definitely a little ugly, but gets the job done. The trick to getting this to work is the cast into an Enum variable of the same type. Again we use typeof() to get a reference to the full class name of the Enum and then cast the results into an int.

Now you can easily work with Enums to put the list of strings into a ComboBox and later retireve the Enum value from the selected string. In a future article, I’ll demonstrate how you can use attributes to show different text than the actual member name.

Categories: .NET, .NET 2.0, C# 2.0

The underlying connection was closed.

December 20, 2006 Comments off

There seems to be a big problem with the underlying code behind the sockets classes that Microsoft uses in their .NET framework. Many people are getting a ?The underlying connection was closed.? error message, but there doesn?t seem to be any consistency to it. I sent a simple test program using the code below to a friend in Singapore and he gets the error. Well, I decided to create a very simple Socket program to see if he gets the error with it as well, and sure enough he does. His Windows XP computer is fully patched too. Some people are getting this error when connecting to a web service, and they have found a way to get around it most of the time, but the error still comes back from time to time even with that patch. This however, isn?t a web service, just a simple WebClient piece of code that connects to a web server.

Microsoft has yet to release anything on this.

WebClient Class

a_url = ?http://www.google.com?;
System.Net.WebClient WC = new System.Net.WebClient();
data = WC.DownloadData(a_url);

The follow socket class also throws the error, not with me, but with some people that I send it too. It seems to be random.

Read more…

Categories: .NET, .NET 2.0, C# 2.0