By Robert Bowen
Once upon a time, when the Internet was dialed-up and 36,600 KBPS was like lightning, I was living in a small town working for a computer retailer and Internet service provider. My boss at the time was… well, let’s just say that customer service was not his priority. Not only would he berate and verbally assault almost every customer who happened to cross his path when he was frustrated by a computer repair, but his relentless tirades caused customers to leave either in tears or on the verge of them.
I wondered during my four-year stint, attempting to clean up the customer service messes he left in his wake, how he managed to stay in business in the years before and since my employment. And the answer was simple: he was a big fish in a tiny pond.

In a town of 18,000 residents, there were only three computer retailers that had qualified technicians who could handle in-house repairs. He was one of them. But as web freelancers, we are swimming in an ocean that is teeming with qualified fish, all waiting for a hook from clients. So, we have to pay special attention to the customer-relations part of our business if we want to build and maintain our client list. The problem is that many of us have spent most of our time throughout the years working for someone else, possibly far from the reach of our employer’s customers. So, our customer service skills may be rusty, or even non-existent.
Also consider our previous articles:
Does It Really Matter?
Meager people skills and miniscule patience make some of us a business hazard when interacting with clients. Some people may not believe that this could be explosive to a freelancer’s reputation, but according to a 2009 online survey by Tealeaf, there is cause for concern:
The survey results also show that online adults are increasingly turning to social media to share their online experiences with others, while simultaneously becoming less likely to alert a company directly—a shift in consumer behavior which extends the business impact of customer experience issues beyond any single transaction.
Given this trend among consumers, we can assume that the same would hold true for our freelance clients, and that the impact of the customer’s experience will be felt long after the experience concludes. This makes it evermore critical for us to maintain as much control as possible over what that impact is, negative or positive.
This is important for freelancers adrift in the design and development ocean, where even the biggest among us still look small compared to the agency sharks that we compete with for work. If a client leaves with a bad taste in their mouth and decides to portray our business in an unflattering light, we have fewer resources than those sharks to seek out and address these word-of-mouth reviews in social media. Bigger businesses have more time, tools and employees to scour social media outlets for mentions of their companies and to rectify complaints.

This was demonstrated to me recently when we awoke to find our Internet access down. After the standard panic and resetting of system, router and modem, we determined that the problem did not stem from our end but rather from our provider’s. Suddenly, we realized that, without a phone book in the building or access to the Internet or to our invoices (which we receive by email, doing what we can to be as paperless as possible), we did not have the phone number of our provider anywhere in the house. After a frustrating hour, we were finally back online and a bit steamed from our time off from being connected. Did we then contact the provider to vent or inquire about the problem? No. We did what Tealeaf’s survey predicted we’d do: we turned to Twitter.
Having mentioned the company by name on Twitter, we were easy to find. Almost immediately, our provider read what we had to say and responded to us on this social media outlet, making sure we were not experiencing any more problems with connectivity. Overall, it made for an interesting lesson in customer service, and it showed where we as small fish might be missing opportunities to nip bad word of mouth in the bud before it spreads into viral gospel. As freelancers who wear every hat in the business ourselves, our time is limited, so we cannot stay on top of every mention of our business out there.
“The number of consumers who contact a company directly in response to online transaction issues declined:
- 26% of online adults who experience problems conducting online transactions then posted complaints on a company’s Website in 2009, versus 32% in 2008.
- 38% of all online adults contacted a company’s call center after encountering problems using the Website in 2009, versus 47% in 2008.”
(Excerpt from Tealeaf survey)
The survey also reports that more than half of adults who spend time online have been influenced by social media in their consumer choices, which reinforces the importance of customer service to the health and growth of our freelancing businesses. A first impression no longer carries as much weight as it once did; each interaction with our clients bears as much on our business as another. We may think that as long as our business dealings end on a high note, that the rocky road that led there will not play a factor in the success of our freelancing career. A 2007 study released by Harris Interactive says different, suggesting that each dealing with our clients needs to be handled with care:
The study reported that 80% of 2,049 US adults surveyed decided never to go back to a business/organization after a bad customer service experience. The study clearly indicates that an organization’s customer service level is a defining factor that will make or break a company… Consumers have increasingly higher expectations of businesses and are willing to walk away quickly from a majority of businesses if those expectations are not met.
The data shows that each and every interaction we have with a client is an opportunity to improve our business standing. because consumers are quicker to go elsewhere after a negative interaction. Even if our strengths do not lie in customer service, we need to ensure that each experience, whenever it occurs during the course of a project, is an agreeable one. Again, as freelancers, we have to deal with our clients at every stage of the project, and so we have to address not only the requirements of the project, but also any customer service issues that may arise in the process.

What We Can Do?
We can do several things to improve our chances of getting positive results from all of our customer interactions. Of course, no one is guaranteed to satisfy all of their clients’ needs and expectations 100% of the time, but we can take steps in the right direction. It starts with taking as much responsibility as we can for the impressions we leave with our customers.
Be Friendly
This one almost goes without saying, but it should be considered from another perspective. Given that the majority of our interactions with our clients might be online, we need to remember that tone and intent does not always translate well to this medium. So, read through your communications to catch anything that may come off negatively. We always want to be aware of the impression we’re making in these seemingly minor moments. As shown before, the weight of an experience is felt long after the moment has passed.
Be Patient
Remember that your client probably does not share your level of expertise in your field. Their questions may not be clear and their feedback not as constructive as it needs to be. Put yourself in their position and be as patient as you would want someone else to be with you. Even if patience is not your strong suit, your customers want to feel that you are listening to and considering their opinions. If you switch off because they cannot communicate with you in your mode of parlance or you dismiss their feedback because they don’t know as much as you do, you will be hurting your business more than your client.

Be Accessible
Another thing that frustrates clients is lacking access to you when they need it most. As freelancers, we pride ourselves on our flexibility and being able to set our own hours. But we have to respect the hours during which our clients work, too, and make ourselves available at those times, so that they are able to share ideas and discuss progress in a back-and-forth conversation. One-sided conversations can easily be misinterpreted without further explanation and just delay the client from achieving their goal.
Be Informative
One of the things Aaron Irizarry said in a recent videocast stuck out. He advised us to mind the skill gap between us and clients and to bridge these informational gaps whenever possible. Help them understand our processes and the reasons for the decisions we make. This gives them more faith in following our advice and increases the chances that they will return as clients.
Keep Track and Get Back
When I mentioned that larger firms have more resources to invest in the customer service outlets that are available to all of us, I didn’t mean that we shouldn’t use those outlets at all. Take advantage of them to track what is said about your skills, or lack thereof, and respond accordingly. You may not be able to respond immediately, but do it when you can. If you find a criticism, consider the points they raise and address them thoughtfully, not dismissively. If they praise you, be gracious and return the gesture in kind.
Be Proactive With Mistakes
As I said in Critical Mistakes Freelancers Make, we are all human, and mistakes happen. Don’t shy away from them or, worse, neglect to acknowledge them at all. Own up to them. This is a time to shine by proactively addressing mistakes before they become an issue that the client feels compelled to bring to your (and other people’s) attention. You’ll show your commitment to the client and project, and it will speak volumes about your character. By owning up to our mistakes, we show pride in our work, and more often than not the client will understand and forgive us.

Go Above and Beyond
Doing all of the above usually puts you in the “above and beyond” category, but you could always push your freelancing business over the top by over-delivering. By giving your client more than they have asked for, you further demonstrate your commitment to making them happy and your pride in your performance. This can be as simple as addressing customer service concerns positively and proactively. It also encourages your clients to come back to you time and again.
Further Resources
Thanks for taking the time to read through the post! Below are a few links to further the discussion of the importance of customer service to your freelancing career. Check them out for a more thorough look at what this topic means for freelancers.
(al)
Tags: Application Packaging, freelance, How To's, Virtualization
Posted by Silverlight Show on Mar 12, 2010 in
Silver Light |
View Original Article
Product Description
Business Intelligence (BI) software aims to bring together different pieces of a business into views that can make comprehending mountains of data easier. BI is everywhere. Applications that include reports, analytics, statistics, and historical and predictive modeling are all examples of BI applications. Currently, we are in the second generation of BI software, called BI 2.0. This generation is focused on writing BI software that is predictive, adaptive, simple, and interactive.
As computers and software have evolved, more data can be presented to end users with increasingly visually rich techniques. Rich Internet Application (RIA) technologies such as Microsoft Silverlight can be used to transform traditional UIs filled with boring data into fully interactive analytical applications to deliver insight from large data sets quickly. Furthermore, RIA applications include 3D spatial design capabilities that allow for interesting layouts of aggregated data beyond a simple list or grid. BI 2.0 implemented via an RIA technology can truly bring out the power of BI and deliver it to an average user via the Web.
Next-Generation Business Intelligence Software with Rich Internet Applications provides developers, designers, and architects a solid foundation of BI design and architecture concepts with Microsoft Silverlight. This book covers key BI design concepts and how they can be applied without requiring an existing BI infrastructure. The author, Bart Czernicki, will show you how to build small BI applications by example that are interactive, highly visual, statistical, predictive, and most importantly, intuitive to the user.
BI isn't just for the executive branch of a Fortune 500 company; it is for the masses. Let Next-Generation Business Intelligence Software with Rich Internet Applications show you how to unlock the rich intelligence you already have.
What you'll learn
- Design rich BI solutions for the masses
- Discover tips for using engaging BI designs for application presentation
- Consume BI data as a service
- Understand and create SaaS models in BI
- Craft BI solutions using the most advanced Silverlight 3.0 technology through C# 3.0
Who is this book for?
There are four core audiences for this book:
- Business intelligence professionals/developers: Cube designers, report writers, SharePoint administrators, and others in this group are looking for a resource to gain additional wisdom on cutting-edge BI concepts. These readers will gain ideas that go beyond the capabilities of the traditional BI tools they are used to
- Senior developers or architects: Developers who are familiar with writing traditional software applications and want to broaden their understanding of concepts in order to include BI fall into this category. Some may have never written any BI applications in their careers but are interested in what BI has to offer. These readers will understand the core BI concepts and how to apply them using application techniques
- CTOs/BI directors: These are senior managers who make strategic decisions with BI. The technical examples will probably be overly technical for these readers. However, the numerous visual aids within this book will help these strategic managers make better decisions after seeing next-generation BI concepts implemented
- BI consultants: These readers may be any combination of the preceding three categories. The BI consultant can use this book as a resource for ideas and examples of next-generation BI designs
About the Author
Bart Czernicki has been playing around with computers since 1988 and has spent years as a professional in the IT field. He currently works as a senior software architect at a software development company.
Buy from:


Tags: Application Packaging, Virtualization
Posted by Silverlight Show on Mar 12, 2010 in
Silver Light |
View Original Article
Introduction
If you work with Silverlight or WPF, you have probably met the phrase “MVVM”. Almost everyone who is anyone in the WPF / Silverlight scene has their own MVVM framework, and their own way of explaining and teaching MVVM. Scary terms like IoC, Dependency Injection, Commanding Frameworks, Event Aggregators, Unit Testing, etc just roll off the tongue of the MVVM experts. This is one of the reasons why MVVM is intimidating for a lot of people. Still, you can create perfectly valid MVVM applications without even knowing what those terms mean. This post will show you my approach to MVVM, which is hopefully simple enough to get you started.
So, what is MVVM? There are tons of blog posts on the topic on the net - for example, take a look at John Papa’s 5 Minute Overview of MVVM in Silverlight. I won’t go into details, but here is my very short summary:
- MVVM allows for real separation between logic and presentation (or developer and designer).
- Model is the data that is displayed in the application. Model is created by a developer.
- View is the User Interface, that is defined in XAML (mostly). View is the responsibility of a designer.
- ViewModel is the logic behind the UI, it handles data retrieval and manipulation, follows the state of the application (such as whether the user has logged on or not). The ViewModel is owned by the developer, and is present in the View as the DataContext.
From our perspective, the interesting part is how the View and the ViewModel are communicating. There are two components to this: databinding (synchronizing data between the View and the ViewModel) and commanding – which is essentially a mechanism that allows the View to notify the ViewModel when user interaction has happened.
Databinding in Silverlight and WPF is pretty powerful. In my mind, the Zen of WPF and Silverlight development is:
“Get the data to be displayed to the client, and trust databinding and XAML – the designer - to do the rest”.
Similarly, the Zen of WPF and Silverlight design is:
“No matter how you want to display the data for the user, XAML and databinding can probably handle it. Only ask a developer to help you after you have tried really hard.”
On the other hand, I always had a bad taste in the mouth when it comes to the commanding facilities of Silverlight (even Silverlight 4). Commanding has two key features:
- Notify the ViewModel if something (usually a user interaction) happens in the View
- Disable UI elements when a command is not available (for example, the save button, icons, etc should be disabled if the user does not have the right to modify an item).
Here is why I don’t like commanding:
- For the designer to be able select a command in Blend, the developer has to create a lot of code – and usually that code simply invokes a method. There is RelayCommand and DelegateCommand to help with this though.
- The biggest issue I have with commanding is that it really ties the hand of the designer. What if I don’t just want to disable the Save button, I want to change its text to “Login first to Save”? What if I am a crazy designer and want to have all the buttons fly in from outside the screen when the user has logged in and is authorized to press them?
- Also, the CanExecute approach can be tedious for the developer. For example, after logging in, you have to re-evaluate pretty much all commands, and call CanExecuteChanged for all of them. For complicated tasks, when there are tons of commands, and their executability (is there such a word) is driven by database settings, the built-in approach may be the right one. But for simpler software, this can be overkill.
The key goals of my MVVM approach
For the project itself:
- Total separation of the designer and developer workflows
- Shallow learning curve for both the designer and the developer
- Allowing both the designer and the developer to remain in their comfort zone, and only use the tools they are familiar with
- Approachable solution for projects with low or medium complexity
For the designer:
- As much Blend support as possible (this is not totally achieved yet due to limitations in Blend 3)
- Use of Visual States to reflect different states of the application
- High level of flexibility
- Almost everything can be done in Blend and XAML
- Shallow learning curve: there is only an Action and a Behavior to learn about
- Create modern UI, including animations, transitions, custom skins, etc.
For the developer:
- Focus only on coding
- Display logic (ViewModel) code is unit testable, including user actions
- Application states can be expressed naturally, via enum values
- Ability to include techniques from other MVVM approaches, such as the MVVM Light Toolkit
So, what do I do instead of commanding?
I use an Action and a Behavior. The Action is for calling methods in the DataContext (that is, the ViewModel). It works similar to the CallDataMethod Action in the Expression Blend Samples project.
The CallDataContextMethodAction
In the attached sample project, there is a TextBox and a Button to illustrate the basic functionality of the CallDataContextMethodAction. The TextBlock is bound to the Message property of the ViewModel, and the Button has the CallDataContextMethodAction applied to it, with the method name set to ShowMsgBox.
Here is the relevant part of the ViewModel (which is set to be the DataContext of the entire form):
1: public string Message { get; set; }
2:
3: public void ShowMsgBox()
4: {
5: if (Message == null)
6: MessageBox.Show("Enter something in the textbox");
7: else
8: MessageBox.Show(Message);
9: }
Here is our Action in Blend:
If the Button is pressed, a MessageBox is shown, with the text entered into the TextBox:
Note: You shouldn’t show a MessageBox from a ViewModel because the designer has no way of modifying what it looks like and how it behaves. However, this is just a test application, and the message boxes are only here to illustrate that the ViewModel actually received the call
So far, it is pretty trivial. What is new in the CallDataContextMethodAction is that it can handle collections pretty well, too. As Glenn Block said in his excellent article The spirit of MVVM (ViewModel), it’s not a code counting exercise, you usually do not need to have parameters for commands. But there are some circumstances when you cannot avoid parameters, Consider the “Greetings to” list in the above picture. We want to display a greeting message for the person the user has clicked on. If the names are displayed in a ListBox, you can bind the SelectedItem property of the ListBox to a ViewModel property, and call the GreetPerson method by capturing the SelectionChanged event (there is a pretty handy EventTrigger built into Blend to help you with this). But then clicking on the same name again won’t fire the SelectionChanged event one more time. Also, what if the designer uses an ItemsControl instead of a ListBox? What if we want to greet the person not by clicking, but by doing some other, non-selective gesture? In this case, we have to have the GreetPerson method either on the person’s ViewModel, or some way to let the main ViewModel know which person we need to greet.
Here is the relevant code in the ViewModel (note that there is no SelectedItem as the names are displayed in a simple ItemsControl):
1: public MyViewModel()
2: {
3: Names = new ObservableCollection<string> {"John", "Smith", "Toby", "Emily"};
4: SG1 = PanelState.On;
5: }
6:
7: public void GreetPerson(string name)
8: {
9: MessageBox.Show("Hello, " + name);
10: }
The Action is now attached to the ItemTemplate:
But the items displayed in the ItemsControl are strings, and therefore the DataContext of the TextBlock is also a string. And a string does not have a GreetPerson method, so how does the Action work in this case? When the Action cannot find a method in the DataContext of the AssociatedObject (the element the Action is attached to, in our case, the TextBlock displaying the name), it tries to find the same method in the parent of the AssociatedObject, and its parent and so on. If such a method is found in the parent, it passes the DataContext (ViewModel) of the AssociatedObject to the parent method. By traveling up the VisualTree, we get to the MainPage, where the DataContext is the MyViewModel class shown above. This class has a GreetPerson method, so that method gets called. The GreetPerson method also has a parameter of string – this will be the DataContext of the TextBlock, thus the name of the person to be greeted. Note, that with CallDataContextMethodAction, we could use a strongly typed parameter for the method, unlike in the case of Commands where the parameter has to be an object.
The big drawback of the CallDataContectMethodAction is that the name of the Method has to be typed in by the designer, thus it introduces the possibility of human error. Hopefully, we will be able to extend the design time experience later on, so that the developer can simply select the Method from a list instead of typing its name.
The VSMChangerBehavior
The other piece of the puzzle is the VSMChangerBehavior. It ties enum values in the ViewModel to Visual States in the View. As VisualStateGroups are orthogonal (meaning each group can be in any state regardless of what states the others are in), this is a very powerful means of visually reflecting the internal states the ViewModel is in. Here is an example:
Suppose we have two panels that we want to show depending on various ViewModel calculations. We have an enum type of PanelState:
public enum PanelState { Off, On }
And here are the two enums:
1: [VisualStateGroup]
2: public PanelState Panel1
3: {
4: get { return _panel1; }
5: set
6: {
7: _panel1 = value;
8: FirePropertyChanged("Panel1");
9: }
10: }
11:
12: [VisualStateGroup]
13: public PanelState Panel2
14: {
15: get { return _panel2; }
16: set
17: {
18: _panel2 = value;
19: FirePropertyChanged("Panel2");
20: }
21: }
For both panels (Panel1 and Panel2) we have their own properties of type PanelState, that fire the PropertyChanged event when set. However, we are using the [VisualStateGroup] attribute to mark these enums as ones that have (or should have) a VisualStateGroup counterpart. Here is what the visual states look in Blend:
As you can see, we have a VisualStateGroup for each PanelState property, The states themselves are called Panel1_On, Panel1_Off, Panel2_On, Panel2_Off. These state names are calculated by concatenating the enum property’s name (which has the VisualStateGroup attribute), an underscore and the name of the enum value:
<PropertyName>_<ValueName>.
After this has been set up, all we have to do is to add the VSMChanger behavior to the Control that has the states we would like to change from the ViewModel:
From this point on, the behavior automatically changes the visual state of the UserControl as the enum values change within the ViewModel. This even includes state changes where the change is animated, as in the case in this simple demo. However, when the state transition is not instantaneous, the developer of the ViewModel may want to be notified when the transition has finished. For this, VSMChangerBehavior includes a callback mechanism. Simply name your callback method <PropertyName>TransitionComplete, and the method gets called when the transition has finished. For example, to show a MessageBox whenever Panel2 has been completely shown or hidden, have this in the ViewModel:
1: public void Panel2TransitionComplete()
2: {
3: MessageBox.Show("Panel2 Transition complete");
4: }
There is one big problem with this behavior, though. Just like in the case of the CallDataContextmethodAction, the designer has to type in the names of the visual states groups and states. As we are wiring up things based on convention, If he/she makes a mistake, the state change will not happen. To help ease this pain, I have added a “VerboseInitialization” property to the behavior.
If it is on, the behavior will write detailed information to the output stream (unfortunately this stream can only be viewed from Visual Studio):
This should help debugging typos and missing states / groups until I figure out how to bend Blend to my will add add a proper designer experience for this behavior.
Summary
So, there you have it. A designer-friendly way to wire up the View and the ViewModel. User gestures can be turned into commands via the CallDataContextMethodAction, and internal states and state changes of the ViewModel can be easily reflected via the VSMChangerBehavior. The later can also be used to disable / enable / hide UI elements in a declarative way that gives much more freedom to the designer than the CanExecute approach. Please let me know what you think in the comments!
You can download the solution with code here. You are free to do whatever you want with it, except say it is yours :)
Tags: Application Packaging, Virtualization