Sunday, December 31, 2006

The Initialize Pattern and the Open & Close Pattern


I have often been confronted with the "initialize" pattern or the "open and close" pattern. For instance there is some object that you instantiate but before you use it you must call an initialization method often like SomeClass.Initialize(). A similar pattern is that with objects that you need to open before usage and make sure that they are closed on usage completion. Often the situation can be handled using "acquisition is initialization". This works well with exceptions and stack unwinding. Sometimes the use of factories can meet the needs. I have a solution that is based on both and is a pattern that I have used when necessary.


In C# I use two classes an outer class and an inner class. The outer class's methods do not have public visibility, except for the constructor and a factory method. The inner class exposes the methods that can be performed on the outer class.


using System;
using System.Collections.Generic;
using System.Text;

namespace NestedTypes
{
public class CResource
{
public CResource()
{
}

protected void Open()
{
}

protected void Close()
{
}

protected void Read()
{
}

protected void Write()
{
}

public CResourceUser CreateUser()
{
return new CResourceUser(this);
}

public class CResourceUser : IDisposable
{
protected CResource resource;

internal CResourceUser(CResource resource)
{
this.resource = resource;
this.resource.Open();
}

public void Dispose()
{
this.resource.Close();
}

public void Read()
{
this.resource.Read();
}

public void Write()
{
this.resource.Write();
}
}
}
}



In this case I have the inner class implement the IDisposible interface which allows for the "using statement" in C#.


using System;
using System.Collections.Generic;
using System.Text;

namespace NestedTypes
{
class Program
{
static void Main(string[] args)
{
CResource resource = new CResource();
CResource.CResourceUser resourceUser = resource.CreateUser();
using (resourceUser)
{
resourceUser.Read();
resourceUser.Write();
}
}
}
}



I have used this pattern for implementing logging facilities. I have used this pattern in multi-threaded environments and I have found that this pattern made it obvious where synchronization must be handled.

Monday, December 18, 2006

Leader and Follower

In order to justify the risk in pursuing a course the leaders and the followers must:
1) Believe in the cause
2) Trust that there is an opportunity for success
3) Believe that the outcome is worth the cost
4) Believe that upon success he will receive his reward

The cause has to be motivating and be aligned with one's goals, responsibilities, or beliefs. The cause should be fully disclosed naming all parties and interests concerned.

There needs to be a real opportunity to succeed. For the follower success includes the allowance to act in the best manner, using one's faculties and skills, being respected, and having a voice that is heard. For the leader success includes the trust that the followers will act in the best manner, using their's faculties and skills, showing respect, and speaking when something needs to be said. The followers will do what they agreed to do and the leaders will do likewise.

There must be a belief that the outcome is worth the cost.

There must be a belief that at the journeys successful end that you will receive your wages. The follower expects the leader to reward them as agreed and that the leader will protect the follower's interests. The leader is in a position of trust and can not violate that trust by hiding the full agenda or by bowing to the interests of unnamed or undisclosed parties.

Wednesday, December 13, 2006

Agile is not about doing as little as possible.

If Agile is about doing as little as possible then I do not practice Agile.

From my understanding Agile reviewed practices and ceremonies and decided that many of them were out dated or not applicable in areas where change occurred often.

The goal is to do only the necessary work with enough staff to handle the necessary tasks. If that means doing less then so be it, but it might mean doing more. Understand that it depends on each situation, organization, and environment. I am sorry that it isn't as simple as you hoped.

Leading and Leadership

Leading as in "being in front of" is not necessarily Leadership.

"Apple is leading the market in the sales of high end MP3 players"
"The University of Utah is leading the way in computer graphics research"

Leading is similar to magnitude while Leadership is like a direction, or Leading is about how far you are in front and Leadership is concerned with going in the right way.

Sunday, December 10, 2006

Common Sense

Maybe the thoughts contained in the following lines aren't generally excepted or understood enough to gain general approval. It seems to be human nature that if over a long period of time something isn't challenged as being wrong or inefficient then the thing is accepted as being right or optimal. Any challenge to the long standing "thing" is usually at first met with resistance, but soon the commotion settles down and reason prevails.

Long experience and empirical evidence of inefficiencies, failures, and abuses is sufficient reason to question the correctness of business management organization and process. These problems have caused people at all levels in business to question the generally accepted "ways" of managing and organizing a business.

In this paper, I have avoided singling out any one management model as being good or bad, or any business leader as being good or bad. Those that have championed change do not depend on the success of my ranting. Also, in this paper, the arguments of those who prefer the status quo will ultimately be forgotten if there is not too much consideration given to their defensive remarks.

The cause of the Worker is, in a great measure, the cause of all people. Many circumstances have, and will arise, which are not specific to a business sector or management style, but are universal, and through which the principles of all those that desire the satisfaction of a "good days work" are affected, and because they are affect by these universal circumstances they are also rightly concerned. The using of employees in such a manner that they are nothing more than a resource, like so much cattle, which destroys self worth and self esteem and ultimately works against a business' need for efficiency and profitability is the concern of every employer and employee that has the capacity of reason.

The Origin and Design of Popular Business Organization and Process.

SOME writers have so confounded the concept of Team with the management organization, as to leave little or no distinction between them. They are not only different but have different origins. A Team is the organizational results of real need. Management organization is an attempt to deal with our weaknesses and pride. A Team promotes the happiness of each member by uniting on goals and needs where management organization is to minimize the negative affects of human vices. Teams encourage working together with a common cause while management organization creates distinctions, distinctions that have no correspondence with business efficiency or profitability. Team-ship is a patron. Management organization is a punisher.

Team-ship, community-ship, sociocracy, or whatever the term, is a blessing, but the common management organization of business in its best state is but a necessary evil in its worst state an intolerable one; for when we suffer, or are exposed to the same miseries by a business organization, which we might expect in a business with no organization or chaos, our calamities is heightened by reflecting that we furnished the means by which we suffer. High ceremony business organization, like government, is the badge of lost innocence; the mansions and estates of CEOs are built on the ruins of the humble home with the white picket fence and have redefined the organization of the family unit. If the intrinsic desires of a clear conscience were obeyed then there would be no need for another set of guidance. Since that is not the case, it is necessary to surrender up a part of the business earnings to furnish a means for the protection of the rest; and this is induced by the same prudence which in every other case advises one to choose the lesser of two evils. Wherefore, security and predictability being the true design and end of business organization, it unanswerably follows that whatever form thereof appears most likely to ensure it to us, with the least expense and greatest benefit, is preferable to all others.

In order to gain a clear and just idea of the design and end of a business organization, let us suppose a small number of persons start a new company, unconnected to existing companies. In this state of natural liberty, team work will be their first thought. A thousand motives will excite them thereto, the strength of one man is so unequal to his wants, and his mind so unfitted for perpetual solitude, that he is soon obliged to seek assistance and relief of another, who in his turn requires the same. Four or five united would be able to found a fledgling company, but one man might labor out the common period of a life without accomplishing any thing; when he had envisioned the business opportunity he could not bring it to market in a timely manner; the continuous burn of capital would drive him to more short term ventures, and every different want call him a different way.

Thus necessity, like a gravitating and organizing power, would soon form our newly found company into a team or society, the reciprocal blessing of which, would supersede, and render the obligations of corporate government unnecessary while they remained perfectly just to each other; but as nothing but heaven is impregnable to vice, it will unavoidably happen, that in proportion as they surmount the first difficulties of team work, which bound them together in a common cause, they will begin to relax in their duty and attachment to each other; and this remissness, will point out the necessity, of establishing some form of organization to supply the defect of moral virtue.

Some convenient empty office will afford them a conference room in which every employee of the company may assemble to deliberate on company matters. It is more than probable that their first by-laws will have the title of "company guidelines", and be enforced by no other penalty than company-wide disesteem. In the first company organization every man, by natural right will have a seat.

But as company portfolio and employment increases, the company concerns will increase likewise, and the distance at which the members may be separated, will render it too inconvenient for all of them to meet on every occasion as at first, when their number was small, their offices near, and the company concerns few and trifling. This will point out the convenience of their consenting to leave the business management part to be managed by a select number of chosen from the whole body, who are supposed to have the same business concerns at stake which those have who appointed them, and who will act in the same manner as the whole body would act were they present. If the company continues to grow, it will become necessary to augment the number of representatives, and that the interest of every part of the company may be attended to, it will be found best to divide the whole into convenient parts, each part sending its proper number; and that the elected might never form to themselves an interest separate from the electors, prudence will point out the propriety of having elections often; because as the elected might by that means return and work again with the general divisions of the company in a few months, their fidelity to the company division will be secured by the prudent reflection of not making themselves a permanent authority. And as this frequent interchange will establish a common interest with every part of the company, they will mutually and naturally support each other, and on this (not on the unmeaning title of CEO/President) depends the strength of the company, and the happiness of the employee.

Here then is the origin and rise of business organization; namely, a mode rendered necessary by the inability of moral virtue to govern the company; here too is the design and end of business organization, that is to say., predictability and security. And however our eyes may be dazzled with snow, or our ears deceived by sound; however prejudice may warp our wills, or interest darken our understanding, the simple voice of nature and of reason will say, it is right.

I draw my idea of the form of business organization from a principle in nature, which no art can overturn, that is to say., that the more simple any thing is, the less liable it is to be disordered, and the easier repaired when disordered; and with this maxim in view, I offer a few remarks on the so much boasted high ceremony organization of most businesses. That it was noble for the dark and slavish times in which it was erected is granted. When the world was overrun with tyranny, child labor, etc., the least therefrom was a glorious rescue. But that it is imperfect, subject to convulsions, and incapable of producing what it seems to promise, is easily demonstrated.

Absolute leadership through a single office (though the disgrace of human nature) has this advantage with their kind, that they are simple; if the company suffers, they know the head from which their suffering springs, know likewise the remedy, and are not bewildered by a variety of causes and cures. But the corporate politics of high ceremony business organization is so exceedingly complex, that the company may suffer for years together without being able to discover in which part the fault lies, some will say in one and some in another, and every new management fad will advise a different course of action for remedy.

I know it is difficult to get over local or long standing prejudices, yet if we will suffer ourselves to examine the component parts of high ceremony business, we shall find them to be the base remains of two ancient tyrannies, compounded with some new republican materials.

First.- The remains of monarchical tyranny in the office of the CEO and other Chief positions

Secondly.- The remains of aristocratical tyranny in the offices of the Executive committees, such as Vice Presidents and Directors.

Thirdly.- The new republican materials, in the persons of the committees, offices, and middle management.

The two first, by being appointed by the Board of Directors or the CEO, are independent of the employees and their business duties; wherefore in a constitutional sense they contribute nothing towards the representation of the needs of the divisions of the company.

To say that the organization of the company is a union of three powers reciprocally checking each other, is farcical, either the words have no meaning, or they are flat contradictions.

To say that the Board of Directors es a check upon the CEO, presupposes two things.

First.- That the CEO is not to be trusted without being looked after, or in other words, that a thirst for absolute power is the natural disease of autocracy.

Secondly.- That the Board, by being appointed for that purpose, are either wiser or more worthy of confidence than the CEO.

But as the same business organization which gives the Board a power to check the CEO by withholding the supplies, gives afterwards the CEO a power to check the lower managers and committees, by empowering him to reject their other bills; it again supposes that the CEO is wiser than those whom it has already supposed to be wiser than him. A mere absurdity!

There is something exceedingly ridiculous in the composition of high ceremony business organization; it first excludes a man from the means of information, yet empowers him to act in cases where the highest judgment is required. The state of a CEO shuts him from the world, yet the business of a CEO requires him to know it thoroughly; wherefore the different parts, unnaturally opposing and destroying each other, prove the whole character to be absurd and useless.

Some writers have explained high ceremony business thus; the CEO, say they, is one, the employee another; the Executive committee are an house in behalf of the CEO; the middle managers in behalf of the people; but this hath all the distinctions of an house divided against itself; and though the expressions be pleasantly arranged, yet when examined they appear idle and ambiguous; and it will always happen, that the nicest construction that words are capable of, when applied to the description of something which either cannot exist, or is too incomprehensible to be within the compass of description, will be words of sound only, and though they may amuse the ear, they cannot inform the mind, for this explanation includes a previous question, that is to say. How came the CEO by a power which the company is afraid to trust, and always obliged to check? Such a power could not be the gift of wise people, neither can any power, which needs checking, be from God; yet the provision, which high ceremony business makes, supposes such a power to exist.

But the provision is unequal to the task; the means either cannot or will not accomplish the end, and the whole affair is an act of suicide; for as the greater weight will always carry up the less, and as all the wheels of a machine are put in motion by one, it only remains to know which office in the company has the most weight, for that will govern; and though the others, or a part of them, may clog, or, as the phrase is, check the rapidity of its motion, yet so long as they cannot stop it, their endeavors will be ineffectual; the first moving power will at last have its way, and what it wants in speed is supplied by time.

That the CEO is this overbearing part in high ceremony business organization needs not be mentioned, and that it derives its whole consequence merely from being the giver of places pensions is self evident, wherefore, though we have and wise enough to shut and lock a door against absolute power, we at the same time have been foolish enough to put the CEO in possession of the key.

The prejudice of business men, in favor of their own corporate government by CEO, Board of Directors, and Executive committees, arises as much or more from personal pride and self serving ambition than reason. Individuals are undoubtedly safer and treated more fairly than in the Industrial revolution, but the will of the CEO is as much the law of the land in Toyota as in Ford.

An inquiry into the organizational errors in high ceremony form of corporate government is at this time highly necessary; for as we are never in a proper condition of doing justice to our work, while we continue under the influence of some leading partiality, so neither are we capable of doing it to ourselves while we remain fettered by any obstinate prejudice. And as a man, who is attached to a prostitute, is unfitted to choose or judge of a wife, so any prepossession in favor of a rotten high ceremony form of corporate government will disable us from discerning a good one.

Thank you Thomas Paine.

Thursday, December 07, 2006

Sunday, November 26, 2006

Leadership and Management

There is no one leader. Typically there is one manager. The leader rises to the occasion and situation. Leader is not a title once bestowed and thusly endures, but it is a adjective for a moment. Granted there are great leaders but what makes them great? Is it that the occasion and situation in which they rise is a situation with a fundamental concern such of freedom or religious belief? Is it that the situation itself is of great concern?

For instance let me give an example concerning the founding of the United States of America (based upon my opinion that the founding of the USA is a great and good thing). A leader arises in a situation to give guidance and share knowledge. The masses of people that lived in the colonies did not come to a common and practical definition of government. The common people may not have ever defined a government and constitution. However the fundamental need was something that was understood or was spreading in popularity. Those that had opinion, education, experience, and vision concerning sovereignty, how power can be used and misused, and other pertinent issues rose to the occasion. These leaders left behind a document outlining what should be valued and what should be shunned. This document then is used in the managing of the affairs.

The "work place" tries to identify a leader and then assign them the task of being "the" leader from that point forward. Maybe it comes from military like organizations, maybe not, I do not know. Just because you were brilliant in one situation does not mean you will be so again in a different situation.

Is a leader measured by his followers? I would think not. The follower can only be measured by how well the follower studies and internalizes the teachings of the leader. That is why I say that one should always understand the fundamental reasons behind a method. Lets say that some "leaders" in software development propose that testing first is better than testing later. I want to know why it may be true and I care less about who said it. As the follower if I understand they why's then I can manage myself and I do not have to be lead continuously.

What if a leader has no followers? It does not reflect that the person did not rise above a situation. Maybe this person was in a unique situation. Or maybe the others in the same situation are blind to the advantage that the leader expounds. The number of followers do not validate or invalidate the leader.

In business the number of people that are under a Manager is important. Head count is an essential part of the leverage and power of a manager in business. This head count should not be confused with "followers" but honestly is more inline with the concept of "cattle and ownership".

I do not believe that Management is a science and Leadership and art. As a matter of fact I do not even separate science and art.

Do we leave tactical issues to Leaders and strategic issues to Managers? I find this to be overly simplistic.

Leaders help define a set of guidelines for the situation as they traverse the situation.

A fundamental attribute of a leader is selflessness. This is not a necessary or needed attribute of a manager. A leader is willing to suffer the results of his guidance along with those that follow. If there is a group that is following a leader and the group fails the leader does not blame the group for being poor followers but instead accepts responsibility for leading those that followed and usually blames himself for not having an better understanding of those individuals that were following. Management behaves differently is this situation.

I do not feel that any other list of leadership attributes come close to that of selflessness.

Can everyone be a leader? Yes in that I think we are all equal in capacity (generally). Will everyone seize an opportunity to lead when it presents itself? No. Not in my opinion. Even if someone is capable of leading in a situation there are infinite reasons why the person may chose to not act.

Here is a snippet on a paper I wrote that includes sections on leadership and management.

Leadership

Maverick Development is based on leadership. Leadership is something above management. All leaders have management skills. The converse is not true. The bar has to be raised on managers. They have to be leaders.

Agile methodologies depend upon emergent processes. Managers cannot control this type of process because of its very nature. Maverick Development goes where ever is necessary to get the work done. When an unexpected situation arises we do not plod along the same path just because the directions say to go that way. Instead, in Maverick, we say, "Hmm, an unforeseen problem. What should we do? Go on? Go back? Go around? ... "

Leadership cannot be taught. Quoting Dr. Huge Nibley,

"At the present time, Captain Grace Hoper, that grand old lady of the Navy, is calling our attention to the contrasting and conflicting natures of management and leadership. No one, she says, ever managed men into battle, and she wants more emphasis on teaching leadership. But leadership can no more be taught than creativity or how to be a genius. The Generalstab tried desperately for a hundred years to train up a generation of leaders for the German army, but it never worked, because the men who delighted their superiors (the managers) got the high commands, while the men who delighted the lower ranks (the leaders) got reprimands. Leaders are movers and shakers, original, inventive, unpredictable, imaginative, full of surprises that discomfit the enemy in war and the main office in peace. Managers, on the other hand, are safe, conservative, predictable, conforming organizational men and team players, dedicated to the establishment.

The leader, for example, has a passion for equality. We think of great generals from David and Alexander on down, sharing their beans or maza with their men, calling them by their first names, marching along with them in the heat, sleeping on the ground and being first over the wall. A famous ode by a long-suffering Greek soldier named Archilochus, reminds us that the men in the ranks are not fooled for an instant by the executive type who thinks he is a leader.

For the manager, on the other hand, the idea of equality is repugnant and indeed counterproductive. Where promotion, perks, privilege and power are the name of the game, awe and reverence for rank is everything and becomes the inspiration and motivation of all good men. Where would management be without the inflexible paper processing, dress standards, attention to proper social, political and religious affiliation, vigilant watch over habits and attitudes, etc., that gratify the stockholders and satisfy security? ... Managers do not promote individuals whose competence might threaten their own position, and so as the power of management spreads ever wider, the quality deteriorates, if that is possible. In short, while management shuns equality, if feeds on mediocrity... For the qualities of leadership are the same in all fields, the leader being simply the one who sets the highest example; and to do that and open the way to greater light and knowledge, the leader must break the mold. " A ship in port is safe," says Captain Hopper, speaking of management, 'but that is not what ships were built for," she adds, calling for leadership... True leaders are inspiring because they are inspired, caught up in a higher purpose, devoid of personal ambition, idealistic and incorruptible... So vast is the discrepancy between management and leadership that only a blind man would get them backwards... "

It is a common known practice when hiring and retaining software engineers to retain what is referred to as the 10x performers. Maverick Development requires the same from its Leadership. Managers that are leaders will be 10x performers.

Trust is the key and here is what Mr. Semler had to say,

"We simply do not believe our employees have an interest in coming in late, leaving early, and doing as little as possible for as much money as their union can wheedle out of us. After all, these are the same people that raise children, join the PTA, elect mayors, governors, senators, and presidents. They are adults. At Semco, we treat them like adults. We trust them. We don't make our employees ask permission to go to the bathroom, nor have security guards search them as they leave for the day. We get out of their way and let them do their jobs."

http://home.att.net/~geoffrey.slinker/maverick/MaverickDevelopment.html

Friday, November 24, 2006

What makes a good Software Design?

What makes a good software design? Can software be good and have a poor design?

I will address the second question first. Can software be good and have a poor design? I think so. Of course this depends on my defintion of good. Good software meets the current goals of the user. For instance the software does what the user wants and it does it with no errors, mistakes, or unwanted side effects. The user usually does not care what language the software was developed with, or what process was used to guide development, or how much the programmers were paid to write the software, or even if the software has a good design.

Software design is a practice that addresses issues the programmers find important. Such issues are changeability, extensibility, understandability, usability, and verifiability (if these are even words).

In my opinion code must meet the usability quality in order for the design to be considered good. What does this mean?

Code is developed to be called or in other words to be used. If the design is such that the code is easily called then it has an improved design. What makes code easily called? If it is easy to setup the state necessary to initiate a meaningful call. What makes state setup easy? That depends on the system and problem domain. Often this is an attribute of coupling and cohesion. Therefore, easily callable code is often losely coupled and cohesive code.

A good software design will make it possible to verify the software. How do you verify software? By using the code. Do you see the relationship? Usable code has a relationship to code verification. The easier it is to setup a call into the system maps directly to the ease of testing, validating, and verifying the sytem.

The test that exercises code is just another user of the code. Therefore when you write code you have at least to customers or consumers of the code. The first customer is some part of the overall system you are developing. The second customer is the test code that exercises the code you are developing. There are always at leat these two customers. If the first customer doesn't exist then why bother writing the code? If the second customer doesn't exist then what will you use in place of testing code to exercise your code?

A good software design is expressed in code that is usable. The easier it is to use the better. This ease of use reflects the coupling and cohesion of the abstract model. Usable software can be used by multiple customers. One customer should be a verification customer which is a piece of code to use your code and check if your code did what is expected. I believe this leads to the important axiom that testable code is code with a good design. I think that testability is a subset of usability.

Geoff

Wednesday, November 08, 2006

Democratic Workplaces

WorldBlu has started a search for the Most Democratic Workplaces.

The WorldBlu Search: November 1, 2006 - February 16, 2007:
The WorldBlu Search for the Most Democratic Workplaces is a GLOBAL search from November 1, 2006 until February 16, 2007 designed to identify organizations from the for-profit, non-profit, government, and education sectors practicing organizational democracy.

Recognizing the Mavericks, Inspiring Others:
We believe there are many highly successful and profitable – yet often unnoticed – examples of democracy in the workplace. These organizations are defying convention, rewriting the rules of business, and pioneering the next generation of organizational design and leadership. The WorldBlu List of Most Democratic Workplaces seeks to shine a spotlight on these champions of freedom and inspire others in the process.

The WorldBlu List of Most Democratic Workplaces 2007:
On March 6, 2007, WorldBlu will announce the first annual WorldBlu List of Most Democratic Workplaces in conjunction with the celebration of Democracy in the Workplace Day.

How it Works:
Organizations apply to have their employees take the online WorldBlu Democratic Workplace Scorecard which measures the degree of organizational democracy in their workplace. The WorldBlu List will be comprised of organizations that took survey and scored at the top level, identifying them as one of the most democratic workplaces in the world. There is no fee to apply.

All Sectors Invited to Participate:
The WorldBlu List is open to any organization from the for-profit, non-profit, government and education sectors, as long as the organization has at least five regular full-time or part-time employees and has been in operation for at least three years.

Learn More + Get Started:
To learn more or have your organization get started now to apply for the WorldBlu List, please go to www.worldblu.com .

If you are interested in discussing "Democratic Workplaces" there is a users group found at Maverick Software Development

Wednesday, November 01, 2006

Composite UI Application Block Model View Presenter

Model View Presenter
is a design pattern support by CAB and the Smart Client Software Factory (SCSF).

A View is a SmartPart.

The Presenter calls methods of the View to update the information the View displays. The View should expose its methods to the Presenter through an Interface. The Presenter stores a reference to the View's interface.

In my examples I have updated UserButton and added IUserButton and UserButtonPresenter.

Here is IUserButton.cs:


using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace CABTestOne
{
public interface IUserButton
{
void SetColor( Color color );
}
}


Here is the new UserButton.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.EventBroker;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
[SmartPart]
public partial class UserButton : UserControl, IUserButton
{
public MyMessagePublisher publisher;
protected UserButtonPresenter _userButtonPresenter;

public UserButton( )
{
InitializeComponent( );
}

private void button1_MouseClick( object sender, MouseEventArgs e )
{
_userButtonPresenter.UserButtonClicked( sender, e );
publisher.UserButtonClicked( sender, e );
}

[CreateNew]
public UserButtonPresenter userButtonPresenter
{
set
{
_userButtonPresenter = value;
_userButtonPresenter.userButton = this;
}
}

public void SetColor( Color color )
{
this.button1.BackColor = color;
}
}
}

Here is the new UserButtonPresenter.cs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.EventBroker;

namespace CABTestOne
{
public class UserButtonPresenter : IDisposable
{
protected WorkItem _workItem;
protected IUserButton _userButton;

~UserButtonPresenter( )
{
Dispose(false);
}


public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}


protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if( _workItem != null )
{
_workItem.Items.Remove( this );
}
}
}

[ServiceDependency]
public WorkItem workItem
{
set
{
_workItem = value;
}
}

public IUserButton userButton
{
set
{
_userButton = value;
}
}

[EventPublication( "topic://CABTestOne/UserButtonClick", PublicationScope.Global )]
public event EventHandler UserButtonClick;

public void UserButtonClicked( object sender, MouseEventArgs e )
{
_userButton.SetColor( System.Drawing.Color.Blue );

if( UserButtonClick != null )
{
UserButtonClick( this, null );
}
}
}
}
[ServiceDependency] tells the CAB framework to get the WorkItem from the collection of services maintained by CAB. The UserButtonPresenter needs the WorkItem in order to enhance the dispose method to remove itself from the WorkItem's Item collection.

How did I know to modify the Dispose methods to remove the Presenter? I looked at lots of code I found on the net.

Listening to a PodCast I learned that a WorkItem is two things.
  1. Scoping Container
  2. Lifetime Manager
[CreateNew] is an attribute added to a property in the UserButton. The CreateNew tells the dependency injector of COB to instantiate a new UserButtonPresenter.

I moved the Event Publisher inside of the UserButton and put it in the UserButtonPresenter. I am not sure if it "should" be there it just seemed like the thing to do.

In the UserButtonPresenter when the UserButtonClicked method is invoked it does two things:
  1. Sets the color of the UserButton
  2. Publishes the UserButtonClick event.

After I completed these code changes I then installed and started using the Smart Client Software Factory. I used the Guidance Package that was installed into Visual Studio 2005 to create a new solution that uses CAB and the MVP pattern. The guidance package auto generated all of the code. Granted the auto generated code included things I had not yet studied but I found that I have turned the learning curve and have enough foundation and a feel for CAB that I am able to understand the auto generated code. So, this will probably be my last blog entry on the Composite UI Application Block. I have a lot to learn still but I can see enough now that I don't feel like I am lost in the dark.

By the way, I have been learning CAB in this fashion because it is part of an approach I am working on called Experience Driven Development (EDD) and has a fundamental practices Design by Use and Software Reconn.

Podcasts and Links about CAB

While experimenting and learning the Composite UI Application Block I am continuously searching for information. I have found these podcasts to be helpful.

Dr. Dobb's .Net Cast

Composite UI App Block (CAB) Internals

Understanding Dependency Injection

The Power of WorkItems, Events, and Services

Cabpedia
is proving to be very helpful.

Monday, October 30, 2006

Composite UI Application Block EventBroker and Publish and Subscribe

As I started learning how to use the CAB EventBroker with Publish (Pub) and Subscribe
(Sub) I found many examples of simple event publishers. However the code was always
confusing because the examples looked similar to this:

  [EventPublication( "topic://CABTestOne/UserButtonClick", PublicationScope.Global )]
public event EventHandler<EventArgs> UserButtonClick;

public void UserButtonClicked( object sender, MouseEventArgs e )
{
if( UserButtonClick != null )
{
UserButtonClick( this, null );
}
}

The confusing part to me was why would UserButtonClick ever be null or not null.
Where did it get instantiated?

As I studied the example code I came across a comment that Pub/Sub should be used
to communicate between views and it should not be used to communicate between a
view and its presenter.

I recalled that a "view" is a SmartPart. My previous example has a SmartPart called
UserButton. So I started modifying the UserButton class.

First I added an event handler to the UserButton to handle "MouseClick" events.
I did this through the designer by getting properties on UserButton and adding the
event handler.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.EventBroker;

namespace CABTestOne
{
[SmartPart]
public partial class UserButton : UserControl
{
public UserButton( )
{
InitializeComponent( );
}

private void button1_MouseClick( object sender, MouseEventArgs e )
{
UserButtonClicked( sender, e );
}
}
}

Then I added an EventPublication attribute to UserButton. (I will omit the using
statements )


namespace CABTestOne
{
[SmartPart]
public partial class UserButton : UserControl
{
public UserButton( )
{
InitializeComponent( );
}

private void button1_MouseClick( object sender, MouseEventArgs e )
{
UserButtonClicked( sender, e );
}

[EventPublication( "topic://CABTestOne/UserButtonClick", PublicationScope.Global )]
public event EventHandler<EventArgs> UserButtonClick;

public void UserButtonClicked( object sender, MouseEventArgs e )
{
if( UserButtonClick != null )
{
UserButtonClick( this, null );
}
}
}
}

An event has a "topic" and a scope. The topic is also referred to as the Event URI.
The topic is the key that identifies an event. I do not mean to imply that there
is a dictionary of events and that the topic is a key string because I have not
inspected the implementation. I mean to say that the topic is used to publish the
event and it is used by subscribers to listen for the event.

The scope specifies the visibility of the event.

namespace Microsoft.Practices.CompositeUI.EventBroker
{
// Summary:
// Defines the scope for a publication of an Microsoft.Practices.CompositeUI.EventBroker.EventTopic.
public enum PublicationScope
{
// Summary:
// Indicates that the topic should be fired on all the Microsoft.Practices.CompositeUI.EventBroker.PublicationScope.WorkItem
// instances, regarding where the publication firing occurred.
Global = 0,
//
// Summary:
// Indicates that the topic should be fired only in the Microsoft.Practices.CompositeUI.EventBroker.PublicationScope.WorkItem
// instance where the publication firing occurred.
WorkItem = 1,
//
// Summary:
// Indicates that the topic should be fired in the Microsoft.Practices.CompositeUI.EventBroker.PublicationScope.WorkItem
// instance where the publication firing occurred, and in all the Microsoft.Practices.CompositeUI.EventBroker.PublicationScope.WorkItem
// descendants.
Descendants = 2,
}
}

WorkItems are a key component when defining scope.

So, I have an event. That's great, but not very interesting. I want something to
listen for the event or in other words subscribe to the event. So I create a class
called MyMessageUser. Remember that all of these classes are in the same project.
I have not yet experimented with Modules.

I found many examples of what an event subscription looks like and so I implemented
MyMessageUser thusly:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.EventBroker;

namespace CABTestOne
{
public class MyMessageUser
{
[EventSubscription( "topic://CABTestOne/UserButtonClick", Thread = ThreadOption.UserInterface )]
public void HandleUserButtonClickEvent( object sender, EventArgs args )
{
int i = 3;
}
}
}


I put "int i = 3;" in the method so that I could place a break point there to see
if and when the method was called.

I set my break point on i = 3 and fired up the application and clicked on my UserButton.
Nothing. So, I made MyMessageUser a SmartPart. Nothing. What was I missing? I couldn't
find any example to shed some light. Then I remember that events are associated
with WorkItems. So I decided to add MyMessageUser to my WorkItem's Items.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
public class MyWorkItem : WorkItem
{

protected override void OnRunStarted( )
{
base.OnRunStarted( );

//Add my pub/sub stuff
this.Items.AddNew<MyMessageUser>( "MyMessageUser" );
//work spaces control the layout of items contained in the WorkItem
IWorkspace mainWorkSpace = this.Workspaces["MainFormWorkspace"];

//Add a user button to this work item.
UserButton db = this.Items.AddNew<UserButton>( "UserButton" );

//Add a control that has a SmartPartPlaceholder that will control the placement of the UserButton
SimpleView simpView = this.Items.AddNew<SimpleView>( "SimpleView" );

//show the view in the workspace...
mainWorkSpace.Show( simpView );
}
}
}


Now I ran it in the debugger and BANG it stopped on my break point in MyMessageUser.
Sweet!


Remember my concern?


        public void UserButtonClicked( object sender, MouseEventArgs e )
{
if( UserButtonClick != null )
{
UserButtonClick( this, null );
}
}

When does the event handler get instantiated? It happens as a result of adding the
SmartPart to a WorkItem. Exactly where it happens I haven't investigated.

Review


  1. SmartParts (sometime referred to as Views) publish events. When the SmartPart is
    added to a WorkItem the CAB framework wires up the event handler.

  2. Any class can subscribe to events. It doesn't have to be a SmartPart or Controller.
    It DOES have to be added to the items of the WorkItem.

Please remember that these are my opinions on how things work and should be set
up. As I learn more about CAB I am sure that some of my assumptions, metaphors,
and descriptions will prove to be inaccurate.

Multiple Events with One Handler

Now I want to push my ideas a bit and see what can happen. Can one event handler
subscribe to multiple events? Why yes it can!


    public class MyMessageUser
{
[EventSubscription( "topic://CABTestOne/UserButtonClick", Thread = ThreadOption.UserInterface )]
[EventSubscription( "topic://CABTestOne/UserButtonClick2", Thread = ThreadOption.UserInterface
)
]
public void HandleUserButtonClickEvent( object sender, EventArgs args )
{
int i = 3;
}
}

Now I need something that publishes this new event topic //CabTestOne/UserButtonClick2.

I decided to make a new class called MyMessagePublisher. Here is the code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.EventBroker;

namespace CABTestOne
{
public class MyMessagePublisher
{
[EventPublication( "topic://CABTestOne/UserButtonClick2", PublicationScope.Global)]
public event EventHandler<EventArgs> UserButtonClick2;

public void UserButtonClicked( object sender, MouseEventArgs e )
{
if( UserButtonClick2 != null )
{
UserButtonClick2( this, null );
}
}
}
}


From my previous experiments I know that inorder to instantiate the event publisher
UserButtonClick2 I have to add it to a WorkItem Items list. When you add an item
to the WorkItems Item list you want to keep the reference it returns so I added
a member variable to UserButton to keep the reference to the MyMessagePublisher.

using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.EventBroker;

namespace CABTestOne
{
[SmartPart]
public partial class UserButton : UserControl
{
public MyMessagePublisher publisher;

public UserButton( )
{
InitializeComponent( );
}

private void button1_MouseClick( object sender, MouseEventArgs e )
{
UserButtonClicked( sender, e );
publisher.UserButtonClicked( sender, e );
}

[EventPublication( "topic://CABTestOne/UserButtonClick", PublicationScope.Global )]
public event EventHandler<EventArgs> UserButtonClick;

public void UserButtonClicked( object sender, MouseEventArgs e )
{
if( UserButtonClick != null )
{
UserButtonClick( this, null );
}
}
}
}


When the UserButton recieves the MouseClick event it then calls the MyMessagePublisher.UserButtonClicked
method.


I modified MyWorkItem to add the MyMessagePublisher to UserButton.


    public class MyWorkItem : WorkItem
{

protected override void OnRunStarted( )
{
base.OnRunStarted( );

//Add my pub/sub stuff
this.Items.AddNew<MyMessageUser>( "MyMessageUser" );

//work spaces control the layout of items contained in the WorkItem
IWorkspace mainWorkSpace = this.Workspaces["MainFormWorkspace"];

//Add a user button to this work item.
UserButton db = this.Items.AddNew<UserButton>( "UserButton" );

//Add my pub/sub stuff
db.publisher = this.Items.AddNew<MyMessagePublisher>( "MyMessagePublisher" );

//Add a control that has a SmartPartPlaceholder that will control the placement of the UserButton
SimpleView simpView = this.Items.AddNew<SimpleView>( "SimpleView" );

//show the view in the workspace...
mainWorkSpace.Show( simpView );
}
}

Now when I run the application in the debugger it stops twice on my break point
inside of MyMessageUser.HandlerUserButtonClickEvent.


Pretty sweet!

Conclusion

The Event Broker and Publish Subscribe functionality of the Composite UI Application
Block is a little tricky to understand. The tricky-ness has to do with finding simple
examples that explain one aspect at a time. Even my example has to build upon the
previous example.

Publishers and Subscribers are "scanned" by the CAB framework when they are added
to a WorkItem. This scanning looks for attributes and if CAB finds EvenPublication
or EventSubscription attributes it auto-magically hooks things up!

I read that SmartParts should communicate with other SmartParts via Pub/Sub and
that SmartParts should not communicate to "presenters" via Pub/Sub. I don't know
why that statement was made and I am confident that the reasoning will become apparent
as I do more.

Thursday, October 26, 2006

Composite UI Application Block Tutorial

I have recently started using the Microsoft .NET Composite
UI Application Block
(CAB) from
Patterns and Practices
. I immediately realized that there is a significant
learning curve and started searching the Web for examples and tutorials. For various
reasons I found the tutorials to be confusing so I decided that when I started to
get things figured out I would share my experience.


Please note that I am new to the CAB and my current understanding may not be correct
with the overall architecture of CAB.


First, down load
CAB
. I use the December 2005 release for C#. I also downloaded the documentation
and labs.


Install CAB and take note of where it is installed so that you can find the necessary
DLLs to include in a .NET 2.0 Windows Forms project.


There are five classes that will be needed to make a simple Windows Form application
using CAB.

  1. Form. You will need a Form.

  2. WorkItem. You will need a WorkItem in conjunction with a Form.

  3. Shell. You will need a class that inherits from FormShellApplication. To create
    a Shell you must have a Form and a WorkItem.

  4. Button View. You will need a UserControl which contains a Button control.

After you create a new C# .NET 2.0 Windows Application open the Toolbox and drag
the CAB DLLs from the "Microsoft Composite UI App Block\CSharp\Source\CompositeUI.WinForms\bin\Debug"
directory into a new group so that you can drag & drop CAB components in the
designer.

Form

The form is just a normal Windows Form. In the designer drag a "DeckWorkspace" onto
the form. Don't make it fill the entire Form inorder to see how the Workspace constrains/controls
the location of UI components such as a Button. Name the Workspace control "MainFormWorkspace".
The name is used as a key in collection therefore it is important to remember the
name you choose.


Workspaces

A Workspace is a place where UI parts will be displayed.


WorkItem


A WorkItem is a container. It is associated to the application when the Shell is
created. When the application is run the CabApplication.Run() calls rootWorkItem.Run().
Inside of your subclass of WorkItem override the method OnRunStarted().

Inside of your OnRunStarted method you can access a collection of Workspaces. Remember
when we created the Form we added a DeckWorkspace and named it "MainFormWorkspace".
Use that name as a key and get an interface to the workspace.

IWorkspace mainWorkSpace = this.Workspaces["MainFormWorkspace"];

So, what can you do with a Workspace. You can call Workspace.Show! But what is it going to show?
This is where it gets a little confusing to me and it took me a while to get any controls to show up on my Form.

Remember we are inside of OnRunStarted() of our WorkItem. The WorkItem has the Workspaces
collection and it has an Items collection. Before you call Show() on your Workspace
you must add your UserControls (that are also SmartParts), but the interesting thing
is that you add these UserControls to the WorkItem and NOT to the Workspace. I am
still new at this so I am not sure why the UserControls are added to the WorkItem
so when I get a better feel and understanding I will post why the architecture is
thus. Remember I just want to get a button up on the Form. I know it has to do with
seperation of concerns.


Shell


A CAB application runs in a shell. You will need a class that subclasses FormShellApplication.
The constructor of your shell will associate the Form and the WorkItem.

You must update your static void Main method to call the run method on your shell.


View

A View is a UserControl that is also a SmartPart. It seems that it has to be a UserControl.
In my first attempt I subclassed Button and couldn't get it to show up on the Form.
So, I made a UserControl and added a Button to that control. Then I put the attribute
[SmartPart] on the UserControl. Once I added the UserControl to the WorkItem.Items
collection and then called Show on my Workspace the UserControl appeared on the
Form.


Source Code

Find your static void Main() method and change it to run your CAB application. The
class that contains Main in my project is Program.cs.


//Program.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main( )
{
new MyFirstCabApplication().Run( );
}
}
}

MyFirstCabApplication is a subclass of FormShellApplication. FormShellApplication
uses generics to associate the Form and the WorkItem.


//MyFirstCabApplication.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
public class MyFirstCabApplication : FormShellApplication<MyWorkItem,Form1>
{

}
}


MyWorkItem is a subclass of WorkItem. The application will call OnRunStarted of
the WorkItem. It is able to do this because the constructor of MyFirstCabApplication
specifies MyWorkItem.


//MyWorkItem.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
public class MyWorkItem : WorkItem
{

protected override void OnRunStarted( )
{
base.OnRunStarted( );

//work spaces control the layout of items contained in the WorkItem
IWorkspace mainWorkSpace = this.Workspaces["MainFormWorkspace"];

//Add a user button to this work item.
UserButton db = this.Items.AddNew<UserButton>( "UserButton" );

//show the UserButton in the workspace...
mainWorkSpace.Show( db );
}
}
}


UserButton is a subclass of UserControl. Because the IDE divides a custom UserControl
into two source files I will include them both. UserButton.cs and UserButton.Designer.cs.
Notice that the UserButton class has the attribute
[SmartPart]. This is essential.


//UserButton.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.SmartParts;

namespace CABTestOne
{
[SmartPart]
public partial class UserButton : UserControl
{
public UserButton( )
{
InitializeComponent( );
}
}
}

//UserButton.Designer.cs
namespace CABTestOne
{
partial class UserButton
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if( disposing && ( components != null ) )
{
components.Dispose( );
}
base.Dispose( disposing );
}

#region Component Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent( )
{
this.button1 = new System.Windows.Forms.Button( );
this.SuspendLayout( );
//
// button1
//
this.button1.BackColor = System.Drawing.Color.Khaki;
this.button1.Dock = System.Windows.Forms.DockStyle.Fill;
this.button1.Location = new System.Drawing.Point( 0, 0 );
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size( 69, 32 );
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = false;
//
// UserButton
//
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add( this.button1 );
this.Name = "UserButton";
this.Size = new System.Drawing.Size( 69, 32 );
this.ResumeLayout( false );

}

#endregion

private System.Windows.Forms.Button button1;
}
}


The Form is also split across two files. I will include them both. Form1.cs and
Form1.Designer.cs.

//Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CABTestOne
{
public partial class Form1 : Form
{
public Form1( )
{
InitializeComponent( );
}

}
}
//Form1.Designer.cs
namespace CABTestOne
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if( disposing && ( components != null ) )
{
components.Dispose( );
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent( )
{
this.MainFormWorkspace = new Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace( );
this.SuspendLayout( );
//
// MainFormWorkspace
//
this.MainFormWorkspace.BackColor = System.Drawing.SystemColors.ControlDark;
this.MainFormWorkspace.Location = new System.Drawing.Point( 12, 12 );
this.MainFormWorkspace.Name = "MainFormWorkspace";
this.MainFormWorkspace.Size = new System.Drawing.Size( 268, 146 );
this.MainFormWorkspace.TabIndex = 0;
this.MainFormWorkspace.Text = "MainFormWorkspace";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size( 292, 273 );
this.Controls.Add( this.MainFormWorkspace );
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout( false );

}

#endregion

private Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace MainFormWorkspace;






}
}

Review


  1. Create a Form.

  2. Create a subclass of Microsoft.Practices.CompositeUI.WorkItem.

  3. Create a subclass of Microsoft.Practices.CompositeUI.WinForms.FormShellApplication.

  4. Update your static void Main to "RUN" your FormShellApplication subclass.

  5. Override the OnRunStarted method of your WorkItem class.

  6. In "your" WorkItem subclass' OnRunStarted add your SmartParts. In my example this
    was the UserButton which is a subclass of the UserControl. Add these SmartParts
    to the Items collection of your WorkItem.

  7. Get an interface to your Workspace. In this case it is the DeckWorkspace that was
    "dropped" on the Form. The DeckWorkspace name is "MainFormWorkspace". This is a
    key to access the Workspaces collection of the WorkItem.

  8. Call Show on the Workspace passing it the UserButton (which is a SmartPart).


SmartPartPlaceholder

After figuring out how to get a Button on the Form I was a little confused that
it filled the entire area of the Workspace.

After some study I figured out how to use Microsoft.Practices.CompositeUI.WinForms.SmartPartPlaceholder.


  1. Create a new SmartPart by subclassing UserControl. I called this SimpleView.

  2. Drag a SmartPartPlaceholder onto the UserControl (SimpleView) and size it and position
    it as you like.

  3. Set the "SmartPartName" to the ID of the UserButton. The ID of the UserButton is
    the key string you use when you add the UserButton to your WorkItem's Item collection.
    Look at MyWorkItem.cs and notice that when I added the UserButton I passed a string
    with the value "UserButton". That string is the key and that key must be the SmartPartName.
    The SmartPartName can be set by viewing the properties of the SmartPartPlaceholder
    that you placed on the SimpleView UserControl.

  4. Add SimpleView to the WorkItem Items collection AFTER you have added the UserButton.
    This is done in the OnRunStarted method of your WorkItem class. It must be done
    after the UserButton was added or it doesn't work.

  5. Change the call to the Workspace Run method by passing the SimpleView instead of
    the UserButton. This is critical.


Below is the source code. Notice that MyWorkItem was modified and that a new class
was added called SimpleView.


//MyWorkItem.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.ObjectBuilder;

namespace CABTestOne
{
public class MyWorkItem : WorkItem
{

protected override void OnRunStarted( )
{
base.OnRunStarted( );

//work spaces control the layout of items contained in the WorkItem
IWorkspace mainWorkSpace = this.Workspaces["MainFormWorkspace"];

//Add a user button to this work item.
UserButton db = this.Items.AddNew<UserButton>( "UserButton" );

//Add a control that has a SmartPartPlaceholder that will control the placement of the UserButton
SimpleView simpView = this.Items.AddNew<SimpleView>( "SimpleView" );

//show the view in the workspace...
mainWorkSpace.Show( simpView );
}
}
}

//SimpleView.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI.SmartParts;

namespace CABTestOne
{
[SmartPart] public partial class SimpleView : UserControl
{
public SimpleView( )
{
InitializeComponent( );
}
}
}
//SimpleView.Designer.cs
namespace CABTestOne
{
partial class SimpleView
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if( disposing && ( components != null ) )
{
components.Dispose( );
}
base.Dispose( disposing );
}

#region Component Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent( )
{
this.smartPartPlaceholder2 = new Microsoft.Practices.CompositeUI.WinForms.SmartPartPlaceholder( );
this.SuspendLayout( );
//
// smartPartPlaceholder2
//
this.smartPartPlaceholder2.BackColor = System.Drawing.Color.Red;
this.smartPartPlaceholder2.Location = new System.Drawing.Point( 29, 28 );
this.smartPartPlaceholder2.Name = "smartPartPlaceholder2";
this.smartPartPlaceholder2.Size = new System.Drawing.Size( 75, 75 );
this.smartPartPlaceholder2.SmartPartName = "UserButton";
this.smartPartPlaceholder2.TabIndex = 1;
this.smartPartPlaceholder2.Text = "smartPartPlaceholder2";
//
// SimpleView
//
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Gainsboro;
this.Controls.Add( this.smartPartPlaceholder2 );
this.Name = "SimpleView";
this.Size = new System.Drawing.Size( 147, 150 );
this.ResumeLayout( false );

}

#endregion

private Microsoft.Practices.CompositeUI.WinForms.SmartPartPlaceholder smartPartPlaceholder2;
}
}


Conclusion

The Composite UI Application Block (CAB) can be a bit tricky. Just getting a simple
example up and running can take a lot of study.

You have to have a Shell ( a subclass of FormShellApplication).

In order to instantiate a Shell you have to have a Windows Form and a WorkItem.

On the Windows Form you must place a Workspace. The Workspace defines the area of
the form where controls (SmartParts) will appear. The name of this Workspace is
used as a key in the WorkItem collection Workspaces. Be sure to make note of your
Workspace name. I used a DeckWorkspace in this example.

SmartParts are subclasses of UserControl that have the attribute [SmartPart].

Add the SmartParts to your WorkItem's collection called "Items".

Call Show on the Workspace. This call is done inside of the WorkItem's OnRunStarted
method.

SmartPartPlaceholders define size and location for SmartParts. The SmartPartPlaceholder
is added to a UserControl. SmartPartPlaceholder.SmartPartname is set to the ID of
some UserControl. The ID of a UserControl is the string passed into the WorkItem
Items collection when you call AddNew on that collection.

Add the SmartPart that constains the SmartPartPlaceholder AFTER you have added the
UserControl that the SmartPartPlaceholder has identified in the SmartPartname.

Introduction to Digerati Illuminatus

This BLOG will contain my thoughts and experiences concerning software development and the related engineering practices as well as the management of the software development effort.

-Geoff