Sunday, April 22, 2007

Using Model View Presenter with VB6 ActiveX And .NET

I started working with a new team a couple weeks ago and so far things are going very well. The next phase of this project is to write some enhancements for an ActiveX Image Viewer component. Yes, you read that correctly...ActiveX in VB6. It's not polite to giggle.
I don't feel comfortable making changes to code that doesn't have test coverage, so I had to come up with a method to test VB6 ActiveX.
I figured that the ActiveX control was really just a view and I should be able to:
  1. Create the view Interface in .NET
  2. Create a Presenter class in .NET that works against the .NET view interface
  3. Expose the .NET view interface and presenter to COM and implement the view interface on the ActiveX control
Sounds simple.

Create the View Interface in .NET

The first  step was to create a simple view interface for this example. I wanted to have a simple text property and buttons for navigating the documents and the pages within the documents.
    [ComVisible(true)]
    [Guid("CC0FE3CD-BE47-46c4-81E9-08499EDF0633")]
    public interface IView
    {
        string Name { get; set;}

        ICommandButton PreviousPageButton { get; }
        ICommandButton NextPageButton { get; }
      
        ICommandButton PreviousDocumentButton { get; }
        ICommandButton NextDocumentButton { get; }
    }

I created another interface for the Command Button object. I did this so I wouldn't have to munge the view interface by including a "Visible", "Enabled" and  "Caption" property for each button on the view. The ICommandButton interface looks like this:
    [ComVisible(true)]
    [Guid("B5482029-1671-4cc1-8BB7-979E933CF81B")]
    public interface ICommandButton
    {
        string Caption { get; set;}
        bool Enabled { get; set;}
        bool Visible { get; set;}
    }
You'll notice the Command button properties are Read Only. The view will return the CommandButton to the Presenter so the Presenter can get/set the properties on the ICommandButton interface. The presenter should not create a Button Control and assign it to the view. That is the responsibility of the view.

Create the Presenter class

Next I create a simple presenter class. In order to work with VB 6 I had to do a couple things. First I had to have a default constructor. COM Interop needs a default constructor. Normally with the MVP pattern, you would create a constructor that takes in the IView interface, however VB6 doesn't support parameters in the constructor. Since constructor injection was a solution, I created SetView() method that takes in the view interface.
    [ComVisible(true)]
    [Guid("867E8A4E-6D08-4c06-9B42-F9C8C12CEBDF")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class Presenter
    {
        private IView view;

        /// <summary>
        /// Default constructor for needed for COM Interop
        /// </summary>
        public Presenter(){}

        /// <summary>
        /// Use Setter Injection since VB6
        /// doesn't allow parameterized constructors.
        /// </summary>
        /// <param name="view"></param>
        public void SetView(IView view)
        {
            this.view = view;
        }

        public void Initialize()
        {
            // Disable all the previous buttons
            view.PreviousDocumentButton.Enabled = false;
            view.PreviousPageButton.Enabled = false;
        }

        public void NextPage()
        {
            view.Name = "Next Page";
        }

        public void PreviousPage()
        {
            view.Name = "Previous Page";
        }

        public void NextDocument()
        {
            view.Name = "NextDocument";
        }

        public void PreviousDocument()
        {
            view.Name = "PreviousDocument";
        }

        private bool isEnabled = true;

        public void ToggleAllButtons()
        {
            view.NextDocumentButton.Enabled = isEnabled;
            view.NextPageButton.Enabled = isEnabled;
            view.PreviousDocumentButton.Enabled = isEnabled;
            view.PreviousPageButton.Enabled = isEnabled;

            //Toggle
            isEnabled = !isEnabled;
        }
    }

Implement the View in VB6

Go dust off your VB 6 we're going in!
I had to implement the view and a class that implemented the ICommandButton interface. The view is easy. I have a class that I can implement the IView  interface on, but how do I implement and interface on the class that already exists? Wrap it I guess. I created a CommandButtonWrapper Class that implemented the interface from the .NET Assembly. Once again I had to create a method to inject the CommandButton control.

In order to wire all the buttons and controls to the presenter I had to write this code on the Init of the ActiveX control.




The rest of the view is very basic and simple. All button click events are delegated to the presenter and the view properties return or set values on the controls of the view.
All in all this solution looks like it is going to work out. I'm concerned about a couple things, but hopeful that I can start test driving this ActiveX control. Wish me luck!

Outstanding Issues

State Management

Where should I be managing state? Typically I keep my presenters stateless, but in this instance I'm thinking that holding it in the Presenter isn't such a bad idea. I would love your thoughts on this.

Monday, March 19, 2007

Free Website Project – Now with Free Hosting!

Today was a busy day for the Iowa .NET User Group Free Website Project.

The good people at PowerDNN.com have offered free web hosting for the websites the Iowa .NET User Group members are building for regional non-profit organizations.



In 2006, we were able to create these sites for these organizations:

http://www.gdmhabitat.org
http://www.stpaulluth.org
http://www.meredithneighbors.org
http://www.soiowa.org
http://www.dmgmc.org
http://www.wdmumc.org
http://www.ciacug.org
http://www.eastvillagedesmoines.com

This year we're working with the following organizations (I'll post links when I have them):

Iowa Rivers Revival
Iowa Heartland Resource Conservation and Development
The Homestead Living & Learning Center
House of Compassion
Greater Des Moines Community Jazz Center, Inc. (CJC)
Mid-Iowa Baseball League

This project is only possible with the help and support of the members of the Iowa .NET User Group who are willing to give up their free time to help other who give.

I would like to thank the following members for their time:

B. C. (The Java Guy. I'm using his initials to protect his identity so the Java community doesn't destroy him J)
David Havenridge
Keith Kmett
Javier Lozano (J. Lo)
Levi Rosol
Nick Parker
Jeff Shaver

If you are reading this and want to help contribute to our community or have an organization that needs help, please let me know. This year was traumatic and we hope to re-bound and make this program even larger next year.

Monday, March 12, 2007

MVP Summit – Day 0: Party with Palermo

Nick Parker, Javier Lozano and I arrived in Seattle yesterday afternoon to attend the MVP Global Summit. The flight from MPLS was an hour late but all in all, no problems with the travel arrangements.

After we arrived at the hotel, we ran into DonXML and all headed over to Jillian's to Party with Palermo.

Jeffery Palermo is a great host and he arranged sponsors to help pay for the 200+ guests! If you are ever at TechEd, or a MVP Summit I would highly recommend that you make time to attend this event. It was a great time and I enjoyed meeting/talking to Jeffery (the host), J.P., and Jeremy.

I'll be heading over to the Microsoft Campus in a bit, but I'm going to take a quick walking tour down to Pike Street Market and pick up a gift for my lovely wife from her favorite store.

Tuesday, January 23, 2007

Database and Continuous Integration

Ben Scheirman wrote a post on the flaws and irritation of dealing with database scripts for a project and looked to Ruby on Rails for inspiration. After I commented on his blog about what our team does, he sent me a email with some questions:

Thanks for the comment on my blog...  I'm wondering:  what tool do you use to create the scripts?

Do you do a drop, re-add?  or a if not exists, then create?

Also, how do you order these?

I was thinking of doing a rails-style migration scheme like this:

0001.Items.Table.sql
0002.Categories.Table.sql
0003.Items.TestData.sql
0004.Items.Categories.FK.sql

but I'm concerned about multiple developers adding migrations and having them collide.  Ideas?

My Response:
Order is an interesting problem. For table changes, we use the "if not exists, then create" strategy. For Views, Functions, Sproc we drop and re-create (including permissions).

What we've discovered is that order only applies to table mods. Our sprocs and views run after the table updates, but we don't have sprocs calling other sprocs (generally) so they don't have order dependency.

As for a tool, we used a SQL project in VS 2003. It would create a .cmd file with all files in the project using an algorithm based on file extension. .tbl are scripted first, then .vw, then .prc, and then finally .sql (or were .sql first, I don't remember). This worked well until VS 2005 dropped the feature that created a command file.

So…we wrote a Nant script that traverses the \sql directory and performs the same logic as the command file. It works, but it is not ideal.

I did see a demo of the new "Data Dude" (VS 2005 Edition for DB Professionals). It was impressive how they solved this problem. They introduced a "build" step that creates a script file of all the changes taking into account dependencies and refactorings (yes, refactorings in the database). Very cool stuff, but I haven't worked with it personally yet. L

I like the ideas behind Rails but do you think your developers are going to do it? They probably have access to the database and will just run the script themselves. I'm asking because we ran into that problem on my current project and the team decided to remove our rights to the testing database. The only way to get scripts on the test server were to have the CI server execute them during the automated build. This forced us to make sure our scripts were in the code repository (I hate typing SourceSafe) and ran without error.

All that being said, I’m still looking for a better solution.

Sunday, January 14, 2007

Tag, I'm it - 5 Things you don't know about me

I got tagged twice. Rob Bogue was first, then I was going to tag Ben Scheirman but he beat me to it.  Anyway here goes…

 

SQL is a B*tch

After buying my first house after graduating from college, I adopted a black lab mix puppy from the Animal Rescue League. Since I'm a geek and didn't think that "Visual Basic", "IIS", or I wasn't going to name her, "Java". So I named her "Sequel". I had spell it out because the vet didn't know how to pronounce,  "S" "Q" "L".

 

At the time I didn't realize the Sequel was a term meaning, "the next one" and every non-geek I ran into thought she was the second dog and assumed something bad happened to first dog.

 

"You shot me!"

As a restless tween, I had a Crossman (no relation to my wife) BB gun to shoot it in the backyard of my parent's house. I left my BB gun in the family room next to the sliding glass door for quick access.

 

On a hot summer day, I was hanging out with my sister, Jody, in the family room. Since it was a hot summer day, was hanging out shirtless. My sister was joking around and picked up my BB gun and pointed it at me. Well the next thing I know,  I hear a POP and my shoulder is numb.  I glance over to my right shoulder and there is a small stream of blood. I looked up to my sister and said, "You shoot me!"

 

It didn't hurt, but the BB was wedged under my skin and my sister had to drive me to the doctors office to get the BB removed. To this day she says she didn't know it was loaded.

 

During the summer of 2001, my girlfriend of 3 years broke up with me. I don't think she envisioned herself married to a tech guy and got a little stir-crazy. I don't hold any ill will.

 

I figured I would have some extra free time without a girlfriend and wanted to build a website of my own. So I came up with a concept called "The Summer Of Tim". It was based on an episode of Seinfield where George declared he was taking the summer off.

 

I needed a website to network with other young, single professionals in Des Moines. The concept was to create a website that people could join that would award points for meeting up at local events.  The site was a success and I was interviews by a sexy reporter named,  Jody Crossman,  from the Des Moines Register.  The story she wrote was also picked up by USA Today.

 

I guess Jody and I hit it off because we are now married with a daughter, Sadie.

 

That's kinda creepy

My sister's  name was Jody Lynn Gifford until she got married.  My wife's name after we got married,  Jody Lynn Gifford.

 

Speaking of names...

My middle name is Jerron. I don't understand where it came from, but it a unique middle name for a guy with the first name of "Tim".

 

Now I get to tag a few people. I’m going to pick Nick Parker, Javier Lozano, Levi Rosol, and Josh West.

Monday, January 8, 2007

VS 2005 & NAnt Integration

 I ran into an issue today that was driving me crazy. I upgraded the version of Rhino Mocks (I love Rhino Mocks!). I thought it would be easy. Download the latest version and drop it into our \lib folder, re-build and “BAM, it’s just that easy”…or so I thought.

After I added the reference, my workstation built correctly and so did the other team members. But when Cruise Control tried to build the project, the build failed! I don’t like to be “the guy” who breaks the build. Since the build server uses the msbuild nant task and VS 2005 uses msbuild (and magic) there is a disconnect between the build processes and I’ve never been able to integrate Nant into VS 2005 in a way that didn’t make the team grumble.

I couldn’t take it anymore so I did some research and found a way to integrate NAnt with Visual Studio 2005. It still isn’t seamless, but I don’t hate it…yet. One gotcha I discovered, you’ll need to name your build file “default.build” for nant.exe to pick it up.

I still wasn’t able to figure out what was causing the build to break, but at least I didn’t check-in and break the rest of team.

Now if I could find a way to run a .cmd or .bat file from the Solution Explorer….GRRR!

Is there an easier way? Should I be using msbuild for my build scripts over nant?

Sans Consolas

I’m concerned about the new security setup in Vista. Now that Vista allows developers to develop without being an administrator on a workstation, I fear the IT/Networking/Security Departments!

Why do I fear them? Because they resist change. Each time I request to have a new anything (font, VS Add-In, or tool) installed on my workstation I have to:

·         Submit a request to my team leader/manager/supervisor

·         After approval, forward the request to the IT Department for review/approval

·         Wait…

·         Respond to questions about the request

·         Wait…

·         Defend the request after it is refused

·         Re-submit the request to the next level of management (Once I had to request approval from the CIO! By the way, CIOs don’t like to be involved in what tools are installed on developer workstations.)

·         Wait…

·         This is typically when a meeting is called between someone in IT, myself, and a mid to upper level manager

·         Finally, get approval to download and install the software

I can understand if I had to go through this process the first couple times I made a request for new software, but I’ve done this a half dozen times and there still isn’t a level of trust between the IT department and myself or the development team.

Today I requested to have the Consolas font installed, we’ll see what happens…