RSS

Why I used 99designs again

Last year I used 99designs to get a logo for my new startup Percollate. I was pretty pleased with it. Apart from fridge-drawings by my kids I’d never had anything designed for me before and it was exciting. Back then I had no idea of the kind of fallout this would create in my local community. I had genuinely never considered that this approach could be viewed negatively by people. After all, it’s got a kind of crowd-sourced feel to it so it has to be good. Right?

Wrong.

Turns out that most designers are dead against sites that take this approach. I say ‘most’ because these site exist and seem to be profitable. Most of these people I see regularly, respect the opinions of and certainly don’t want to upset. To get an understanding of their arguments check out http://antispec.com/.

A few weeks ago I enlisted 99designs for a second time to help me with a logo for Awedience. Clearly, I hadn’t forgotten what happened last time so why did I do it?

Alternatives

One of the suggested alternatives a year ago was to engage my local community. Actually, I like this idea. At the start of the year I embarked on a web-based side project and decided that I didn’t want to be involved with the design / UI side of things. To a packed audience I announced the project and explicitly asked for people to come join me and build it. I had dozens of conversations about how exciting the idea was but not a single offer of design interest. Not one. So, as time was of the essence, I got on with it myself.

Design is Subjective

Most people will agree that Wagner was a genius. Fewer people, however, will find his work to their taste. It’s subjective. Getting into a relationship with a designer really worries me because our tastes might simply be misaligned. Having to terminate a contract after weeks of work would be devastating. 99designs is a great way to quickly find someone that seems to share your particular, personal, subjective tastes.

99designs has Changed

99designs allows you to throw your net to the whole community at the start of a competition. However, within just a few days you have to pick a handful of finalists. I appreciate that this argument will not hold much water for many people reading this but it does mean that those unlikely to win find out quickly.

Awedience is Multi-sourced

The logo came from 99designs. The theme was bought from ThemeForest and tweaked by one of my advisers. For my part, I have be putting in 12 hour days for some considerable time building the application frontend and associated cloud services. The point I’m making is that I have considered the startup as a whole and thought carefully about how best a build each individual part.

We ALL do Spec Work

Nobody wants to work for free. However, unless you work 9-5 and are never called upon to speculate or take a risk, at some point, you’ve done spec work. I can only speak for my own industry and experience, but here are two concrete examples…

Tenders for Technical Contracts

At my previous company we built a business offering platforms to various financial and government bodies. At no point were we able to simply show our previous work and get handed a contract. Here’s how we would spend the man-months:

  • Understanding the client’s requirements
  • Infrastructure design
  • Integration understanding and design
  • Failure identification and problem solving
  • Cost analysis
  • Pre-Pitch documentation
  • Presentation creation
  • Presentation planning
  • Presentation practice
  • Travel to client offices
Guarantee of income: NONE. 

Technical Job Inteviews

Over the years I have been on both sides of the job interview table. Today there is more background information a potential employer can pre-read (e.g. StackOverflow), but the process was almost always the same:

  1. Spend time writing a CV
  2. Spend time searching for a position
  3. Attend first interview – do we like you and is your shit together (at least on paper)?
  4. Attend second interview where you’ll sit our tests and actually show us what you know. (Some companies I know also expect you to deliver a formal presentation of your work).
Guarantee of employment: NONE.

Cost / Benefit Analysis

The price is great ($200) and the results are good enough. Actually, I love our logo but then, as I said previously, it’s subjective. Up until today I had only had positive feedback for Awedience.com – including designers from my local community. Will today’s revelation change their opinions?

In Conclusion

I do not hold with the argument that designers are being treated differently to the rest of the world. Companies like 99designs have come into an established industry and disrupted it. Telling everyone not to use these new services will not work. Designers and design companies either need to find a better solution to the problems raised in this post or concede the ground.

Finally, I believe in open, constructive discussions. Apart from spam, I won’t delete any comments from this post.

 
2 Comments

Posted by on July 16, 2012 in Startups

 

Tags: , , , ,

An Alternative to Job Recruiters?

Over the years I have interviewed a reasonable number of technical people for jobs. Some came from agencies, some directly, some recommended. ALL were interviewed, by us, in exactly the same way.

I still receive a regular flow of emails from recruiters asking if I would consider a candidate or if I would consider myself for a vacancy they are handling. Even though I’m not looking for either at the moment I still try to respond to all emails out of courtesy. One of the huge omissions from this system is the name of the company that’s hiring. Now, I understand why the recruiters do this; they don’t want me to go directly to the company because they’d lose their commission. But, in an era where the biggest deal-maker or -breaker of any job is the company and its culture, this information cannot be left out.

So, enter roundabout.io. I’m quite sure that this isn’t the only site of its kind, but it’s the one that came to my notice today. It cuts out the middleman and lists the job description AND the company. Nice. The only thing I think is still missing is salary; or at least salary range. Whilst I agree that company and culture are critical, so is being able to pay your mortgage! Maybe, as an industry, we’re not quite ready to be that open about salaries yet, but this is certainly a step in the right direction.

 
Leave a comment

Posted by on June 21, 2012 in Jobs

 

Tags: , ,

The Apprentice – Keeping Europe Firmly in the Valley’s Shadow.

So, the results are in and Ricky Martin is Lord Sugar‘s new ‘apprentice’. This is a bad decision. The UK’s Enterprise Champion, responsible for promoting entrepreneurship, should be a catalyst enthusing more people to ‘poke the box’. In short, he failed. Here are the 4 finalists, their business plans and my thoughts…

Nick Holzherr – Online Recipe Ordering

I think it’s fair to say that Lord Sugar didn’t understand the concept. Fair enough, investors rarely get involved with something they don’t ‘get’. However, recipes are big. Ever more sites, apps and shows are appearing that centre around cooking. There’s a lot of money to be made from product placement and commission from sales. Nick fell down by not referencing the existing market with examples of profitable counterparts. Also, if he’s written a working prototype ‘button’ hosted on existing sites then why not evidence the traction achieved?

Jade Nash – Lead Generation Call Centre

Jade did well during the process; clearly, by reaching the final. However, her business plan sucked. So, no surprise that she wasn’t ‘hired’. On the assumption that business plans were part of entrants’ submissions, though, I find it extremely disingenuous that Jade was allowed to enter the process. Why allow someone to go through an 11 week ordeal, with the associated opportunity costs, if she was never going to win?

Tom Gearing – Wine-based Hedge Fund

An innovative idea that combined two existing markets to create a new one. Nick Hewer commented to Lord Sugar that it could be an extremely exciting and profitable business. Lord Sugar’s criticism were based around not knowing the market and his discomfort about investing other peoples’ money.

Ricky Martin – Niche Recruitment Agency

Ricky is a very ‘backable’ individual; but his business plan should not have won. If this was The Apprentice 2009 then he would have triumphed easily. He will no doubt create and run a successful business. I agree with Lord Sugar here; it’s a safe bet.

Conclusion

I remember, vividly, a conversation I had with a Cambridge-based entrepreneur/investor about scale. He said “If you want to be huge, go to the valley. Europe and the UK doesn’t have the capital or stomach for ground-breaking, risky startups.” Ricky’s idea is not entrepreneurial. He knows the market well, but that’s because it already exists. Entrepreneurship should be about creating new markets, pushing boundaries and inventing new ways to solve old problems. The Apprentice should have excited and inspired us. It didn’t.

So, enjoy the continued coolness of the shade cast over us by our US cousins. If our Enterprise Champion cannot shine a little sunshine on us then who can?

 
Leave a comment

Posted by on June 3, 2012 in Startups

 

Tags: , , ,

Are funded startups anti-competitive?

Let’s start this post with a hypothetical…

Imagine a town with a supermarket and a bakers. The bakers has a sensible, sustainable business model, is profitable and provides a good living for its staff. They make ‘better’ bread than the supermarket and some customers decide that that’s important to them. The supermarket bread is not ‘bad’ either. One day the supermarket decides that it doesn’t want the competition. It has a substantial war chest and start giving bread away for free. This is not sustainable for the supermarket, but it doesn’t need to be. After a short period the bakers loses too many customers and closes. Now the supermarket can put prices back up to their normal prices – or beyond.

We’d all agree that this is not a good situation and, in fact, the state regulates against this activity.

Now consider 2 startups. A has a sensible, sustainable business model, customers and profit. B takes a huge injection of capital. B can then offer a similar (even slightly ‘worse’) product or service for free.

Is this situation any different from our hypothetical example? There is no legislation to curb this activity and, clearly, the investors in startup B must have envisaged an exit based on a sustainable business.

So, my question to you is “is this anti-competitive?”. I look forward to your comments.

 
1 Comment

Posted by on April 18, 2012 in Startups

 

Stowaways on your startup escape path

This is a response to Daniel Tenner‘s post A startup escape path. The basic conclusion of the article is that, rather than simply jumping off the cliff, potential entrepreneurs should plan their exit from corporate life. Overlap what you’re doing with what you want to be doing until you have an idea that you can hit the road running with. This is sound advice but neglects to mention a major problem: your employment contract.

A standard employment contract will say, very explicitly, that everything you do, whether in office hours or not, remains the sole intellectual property of your employer.

This is all-encompassing. The idea for a novel you had whilst on holiday, the new tennis technique you discovered one evening, the great iPad game that just ‘came to you’ in the shower. Whilst your employment contract is in force, these are all owned by your employer.

So, if you’re going to attempt this escape path you have two choices:

1. Tell your employer

Talk with your immediate boss and tell him/her what you’re doing. Assuming they don’t have a problem with your activities ask them to send you an official email or signed letter. This should say that they are aware you’re doing X, that it has no bearing on your ability to perform your duties and that the company lays no claims to it. This is your protection so make sure you are honest about what you’re doing.

The down-side to this is that you’ve now waved a flag with “I’m planning to leave” written on it. If you do, eventually, jump off the cliff then no harm has been done. However, if you decide to stay then you may have blotted your copybook.

2. Don’t tell your employer

You wouldn’t dream of asking our employer if it was OK to play in a band on the weekend so why should you tell them about any startup ideas? If you’re working on this in your spare time then it should be none of their business (literally!). The upside of this is if you decide that entrepreneurship isn’t for you; you can just carry on with your current job and no one is any the wiser. The big problems come if you take your escape path.

At any point in the future your employer can lay claim to the startup you’ve built. If they can show that you started your company / idea / product whilst they employed you then it’s pretty much game over. They may be entitled to, potentially, all the equity in your company plus payment of any profits generated by the company over the years. There are some shades of grey though. If you can evidence that your employer knew what you were doing then any judge would question why they waited until all the work had been done before filing a claim.

Conclusions

This is a very awkward situation and, unfortunately, current UK employee contracts stifle innovation. Your employer is in a strong position to disrupt your innovations in any number of ways if you, quite sensibly, test the wind before jumping off the cliff. If you’re an entrepreneur then I’d love to hear how you dealt with this situation. Please use the comments to tell me your experiences.

 
1 Comment

Posted by on January 3, 2012 in Startups

 

Tags: , ,

A Year in the Life of an Entrepreneur

Most entrepreneurial retrospectives are written at the point of success. Once you’ve made your millions it’s easy to be introspective and say where you went wrong. I haven’t got to that point yet, but I will. I’m one year into what I hope I’ll spend the rest of my life doing. If you’re about to jump off the same cliff then maybe you’ll find some of this useful?

Don’t Give Yourself A Year

My wife and I agreed to a one year runway in which to find a repeatable business model. This is far, far too long. In hindsight, we should have said three months or even just one. Given a whole year to do something, you’ll spend most of it doing the wrong things. The fear of failure is a very powerful driver. That’s why people study harder the nearer they get to an exam. Without that imminent risk of having to pack your bags and go home, you won’t push yourself enough.

Don’t Go It Alone

Ideally, this would be a co-founder – someone equally invested and equally in fear of the game ending. But there are plenty of other alternatives if one can’t be found. I have two sets of people that I rely on. Firstly, a number of superb, brutally honest advisers and, secondly, my wife. You need people, who you respect, who can beat you up on a regular basis and really challenge you about what you’ve done today / this week / this month. The reason you need these extra people is covered next …

Recognise Your Abilities

Your technical, sales, business or marketing abilities are as nothing compared to your ability to lie to yourself. Left to your own devices you will convince yourself that:

  • users need that feature
  • it’s not ready to ship yet
  • it’s OK to code all day
  • you need to build a platform for X

You cannot see the lies you tell yourself. Let someone you trust help you recognise that.

Assumptions Will Kill You

The reason Lean Startup is so essential is that it requires you to confirm your assumptions. Not with yourself or someone on your team, but with your customer – someone who might actually pay money for your product or service. Here’s one of my biggest assumptions:

Early on I had a prototype application that, essentially, worked. Trouble was, it was slow and wouldn’t scale to more than a few users. I assumed that nobody would pay for that version because it wasn’t quick enough. What an idiot. I never tested whether people would be happy for the product to email them when complete or even if it ran overnight. Bottom line: I could have had revenue from as early as February.

The Wrong Location Can Be Hard

We don’t all live in The Valley or within walking distance of Silicon Roundabout. In today’s global economy it’s always been possible to work remotely and run a successful business. The problem with start-ups is that you need a network around you. Companies are formed, founders introduced, investors intrigued and future users ignited by face-to-face meetings. I live just outside Cambridge which holds an admirable number of events. However, London is where it’s at and it costs me £50 every time I ‘pop’ in. This is not impossible, but it soon ads up. So, if you can, consider making your geography easier.

Know Who Your Customers Are

I have spent a lot of time talking with the wrong people over the past year. This is in no way disrespectful to them, it’s just that they weren’t my customer. For far too long I concentrated on the technology of my product and spoke with those who understood it. This was wrong. Figure out who your customers are as early as possible and spend a disproportionate amount of time engaging them.

Work Hard

I hope this goes without saying? However, it took me a long time to re-jig my working hours for maximum effect. For months I struggled to work evenings before I made a change. We have two young boys and, after stories and bedtime talks, I was falling asleep myself. Now I start work at 5am every day. It means my evenings are shorter and I watch significantly less TV but, hey, make the choice. You can, genuinely, work 14+ hours a day for prolonged periods.

Give Something Back

I was surprised how early it’s possible to give something back to the startup community. Part of being an entrepreneur is learning to learn fast. Within weeks I had some knowledge that some of my peers didn’t. Because we’re all trying to do something unique we all have experiences we can share – almost immediately. I mentored at Startup Weekend Cambridge in March, less than three months into my free-fall, and it was a hugely rewarding weekend. BTW: you’ll find that you can critique someone else’s ideas much more honestly than you can your own!

Attend Lean Startup Machine

Seriously. Go. Now.

I went to the London boot camp in September and the results were astonishing. Being forced to step far outside your comfort zone for 2 days was the best money I’ve spent all year. After the event I came away with a defined, validated customer segment and problem. The next London event is on February 3rd 2012 – you won’t spend better money.

Finally, I look forward to meeting more of you in 2012. I love being part of this pay it forward community and I believe that what we’re all attempting to do can have profound effects on, well, everything.

 
Leave a comment

Posted by on December 21, 2011 in Startups

 

Tags: , ,

Should you choose Silverlight?

There seems to be a bit of controversy surrounding Silverlight these days; in case you hadn’t noticed. This post is my two-penneth on the current situation and what, I think, the future holds.

I’m a staunch advocate of Silverlight, for now. Especially given the current alternatives. My conviction is such that I’m building a startup that uses Silverlight to test the business model, Percollate. Because of my history of C-level languages and Microsoft development environments, the segue into Silverlight was almost painless. Clearly, it will not be around for ever, but for now it’s hard to see a better alternative.

Here are my thoughts with a little more structure:

Silverlight is Free

The compiler is part of the runtime which is freely downloadable. Microsoft provides a great development environment, Visual Studio and offers the Express Edition for free. There are also 3rd-party developer tools available; made possible by virtue of the free compiler and the reflective nature of the BCL.

A Decade of Support

Microsoft recently announced that they would be supporting Silverlight until the end of 2021. That’s 1 decade. 10 years. 120 months.

Compare this to an open source framework like, say, Ruby on Rails. When ‘Ruby on Rails with Feathers and Neon Lights v2’ comes along, the best developers from the community will jump ship. That’s not a criticism, it’s just that they tend to be trail-blazers looking for the latest innovation.

However, Microsoft will still be fixing the bug that you find in their framework in, say, 8 years time. Considering that 1 year is a lifetime in software development, this level of support is not to be sniffed at.

Now consider this: have you ever worked on a project that took 10 years to complete? How about 3 years? If the answer is yes to either of those questions then you’re probably not using anything as elegant as Silverlight. I don’t know any developers or business owners who are having to plan into the next decade and basing today’s framework decisions on that information.

Know your customer

This section could also have been called ‘It doesn’t work on an iPad‘.

I recently took Percollate to Lean Startup Machine. My pitch of the problem and solution received great responses from the room but, when the S word was introduced the number of interested delegates dwindled. This was at the point when none of us knew who the customer was.

My point is that working on an iPad / iPhone etc is important if you’re producing a consumer application. If, however, you are solving a business problem you don’t necessarily need that reach. As an example: during our private beta trials some customers were borrowing neighbours laptops or digging out old PCs to use our application. If you’re building something where the value proposition is high enough, people will put down their iPads for a few minutes.

Go Rich and Narrow

I love the new developer funnel for Windows 8 / WinRT. You can be a C# developer, a C / C++ developer or an HTML5 / CSS3 developer and yet all compile your work into a native Windows 8 application. Superb. The building blocks of Silverlight (XAML and C#) are the basic of this richer environment.

My hope is that Microsoft also inverts this funnel so that Silverlight / C# developers can ‘compile’ their applications to HTML5 and CSS3. Here’s hoping!

It’s good!

It really is very good. You can easily find a multitude of posts that cover the benefits and delights of Silverlight far more eloquently than I can do here. However, the use of observable data binding, GPU acceleration, compile-time validation and now 3D XNA game integration make it a great environment to work in.

Finally, the bad…

Microsoft engineers produce great works but, alas, its management has failed recently. Quite frankly, someone at Microsoft owes the developer community a thumping great apology. The veil of secrecy about new frameworks and platforms is damaging our infrastructure. You need to talk to us more. Seriously. Talk to us.

 
1 Comment

Posted by on December 19, 2011 in Silverlight

 

Tags:

CustomActions (ItemAdorners) in PivotViewer v2

You can download the example solution here.

PivotViewer v1 introduced the concept of CustomActions on tiles. Enabling the behaviour was a 3-stage process. Firstly, you had to implement your own PivotViewer control and override the GetCustomActionsForItem method. Secondly, you had to write some CustomAction-derived classes. Thirdly, you had to handle the ItemActionExecuted event that the PivotViewer control raised in order to evaluate which CustomAction had been executed. This was not an ideal approach.

PivotViewer v2 has a much richer framework for adding custom functionality to your tiles. I’ll cover some advanced techniques in my next post but, for now, I’ll show you how CustomActions have evolved in this version.

The new version also takes a 3-stage approach, but it’s a lot less invasive of the PivotViewer control. For one, you dont’t have to implement your own custom class any more.

Step 1: Creating the ItemAdorner Style

The new PivotViewer control allows us to define a style for the CustomActions; now called ItemAdorners. This is just a standard Silverlight style, but the trick is to include a PivotViewerDefaultItemAdorner control.

<p:PivotViewer.ItemAdornerStyle>
  <Style TargetType="p:PivotViewerItemAdorner">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="p:PivotViewerItemAdorner">
          <p:PivotViewerDefaultItemAdorner 
            IsTabStop="False"
            DataContext="{TemplateBinding Content}"
            CommandsRequested="GetCommands"
            IsItemSelected="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsItemSelected}" />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</p:PivotViewer.ItemAdornerStyle>

Notice how we’ve bound the IsItemSelected property. This allows the control to hide itself when the tile doesn’t have focus. Later, we’ll be wiring up the GetCommands event but first we have to create some commands.

Stage 2: Creating Commands

Any command associated with the adorner must implement a new interface IPivotViewerUICommand. This extends the, now familiar, ICommand interface and retains some familiar members from CustomActions in v1…

using System;
using System.Windows.Input;

namespace System.Windows.Controls.Pivot
{
    public interface IPivotViewerUICommand : ICommand
    {
        string DisplayName { get; }
        Uri Icon { get; }
        object ToolTip { get; }
    }
}

So, let’s create a simple Hello World command. We’ll pass in a reference to the underlying item that is the data source of our tile so that the command has access to its caller…

public class HelloWorldCommand : IPivotViewerUICommand
{
  private readonly Person _person;

  public HelloWorldCommand(Person person)
  {
    _person = person;
  }

  public string DisplayName
  {
    get { return "Hello World"; }
  }

  public Uri Icon
  {
    get { return new Uri("http://dev.opera.com/articles/view/opera-extensions-hello-world/hello.png"); }
  }

  public object ToolTip
  {
    get { return "Click this to say hello"; }
  }

  public bool CanExecute(object parameter)
  {
    return true;
  }

  public event EventHandler CanExecuteChanged;

  public void Execute(object parameter)
  {
    MessageBox.Show(_person.Name + " says 'Hello'");
  }
}

Stage 3: Connecting the Commands

Lastly we’ll add a handler for the PivotViewerItemAdorner’s GetCommands event where we’ll instantiate and add the commands…

public partial class MainPage : UserControl
{
  private void GetCommands(object sender, PivotViewerCommandsRequestedEventArgs e)
  {
    e.Commands.Add(new HelloWorldCommand(e.Item as Person));
  }
}

This is the result:

In my next post I’ll show you how you can get creative with ItemAdorners in ways that weren’t possible in v1.

You can download the example solution here.

 
25 Comments

Posted by on October 28, 2011 in PivotViewer

 

Tags: , , , , , , ,

How to Ask for Feedback

Yesterday, the summation of 48 hours of very hard work was a pitch competition at Lean Startup Machine, London. I talked about what my team members and I had learnt about TweetPivot and Lean Startup methodology. Unfortunately, we didn’t win; but we did learn an incredible amount. To continue learning I asked for some feedback from the judges. Here’re my recommendations for how to do this:

1. Don’t ask what they thought

If you ask someone this question you put them in a difficult position. The feedback they give depends on how well they know you, your mood, their mood and whether they think you’re just looking for a boost. 9 times out of 10 they’ll say what they think you want to hear.

2. Don’t ask if they have any negative feedback

This is better than #1 but you still present the person with the same dilemma. They are very likely to answer ‘No, it was wonderful’. You’ve learnt nothing.

3. Ask them, specifically, for negative feedback

Perfect. You’ve explicitly given them permission to give you negative feedback. You can’t control how damning they’re going to present this, however, but you’ve removed the risk from them. If they say ‘nothing’, challenge them.

Positive feedback’s great, but you’ll learn much more from honest, negative feedback.

 
2 Comments

Posted by on September 19, 2011 in Lean Startups

 

Tags: , , ,

Efficiency Strategies for PivotViewer

Joris Dries started a Twitter conversation this morning about getting decent performance out of the PivotViewer in SL5RC. So, I thought now would be a good time to gather a bunch of ideas I’ve had over the past few months and put them all in one post. This might not answer Joris’ question directly, but it does satisfy the title.

You can download the complete source code of the examples here.

What I’ll do is build a number of scenarios and compare them against a baseline. Measurements will not be empirical but rather based on when the user thinks the PivotViewer is ready for use. For background info this is the laptop I’m running these tests on:

  • Windows 7 Ultimate x64 SP1
  • Chrome 13
  • WEI: 5.0
  • Intel i5 2.27GHz
  • 4GB RAM
  • Non-SSD HDD

Setting the Baseline

I’m going to start with a data class and a method for creating a sample set from it. This will allow us to stress test the new PivotViewer control. I’m not going to include the code for this here as it’s rather long-winded and not the focus of this post. It’s all in the sample solution.

public class Person : INotifyPropertyChanged
{
    public string Forename;
    public string Surname;
    public int Age
    public string Address1;
    public string Address2;
    public string Address3;
    public string Address4;
    public string Postcode;
    public string Sex;
}

And here’s the footprint of the method for creating a pseudo-random set at runtime that we can databind with:

public static ObservableCollection<Person> GetSampleData(int sampleSize);

Now let’s build some simple xaml so we can show our data. This example uses the new PivotProperties and PivotViewerItemTemplate markup and just needs us to specify an ItemsSource at runtime:

<UserControl x:Class="XamlTileEfficiency.NoEfficiencies"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:pivot="clr-namespace:System.Windows.Controls.Pivot;assembly=System.Windows.Controls.Pivot"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <pivot:PivotViewer x:Name="pv">
            <pivot:PivotViewer.ItemTemplates>
                <pivot:PivotViewerItemTemplate>
                    <StackPanel Orientation="Vertical" Height="150" Width="100" Background="LightBlue">
                        <TextBlock Text="{Binding Forename}" />
                        <TextBlock Text="{Binding Surname}" />
                        <TextBlock Text="{Binding Age}" />
                        <TextBlock Text="{Binding Sex}" />
                        <TextBlock Text="{Binding Address1}" />
                        <TextBlock Text="{Binding Address2}" />
                        <TextBlock Text="{Binding Address3}" />
                        <TextBlock Text="{Binding Address4}" />
                        <TextBlock Text="{Binding Postcode}" />
                    </StackPanel>
                </pivot:PivotViewerItemTemplate>
            </pivot:PivotViewer.ItemTemplates>
            <pivot:PivotViewer.PivotProperties>
                <pivot:PivotViewerStringProperty Binding="{Binding Forename}" DisplayName="First Name" Id="ForenameId" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Surname}" DisplayName="Last Name" Id="SurnameId" Options="CanFilter" />
                <pivot:PivotViewerNumericProperty Binding="{Binding Age}" DisplayName="Age" Id="AgeId" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Sex}" DisplayName="Sex" Id="SexId" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Address1}" DisplayName="Address1" Id="Address1Id" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Address2}" DisplayName="Address2" Id="Address2Id" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Address3}" DisplayName="Address3" Id="Address3Id" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Address4}" DisplayName="Address4" Id="Address4Id" Options="CanFilter" />
                <pivot:PivotViewerStringProperty Binding="{Binding Postcode}" DisplayName="Postcode" Id="PostcodeId" Options="CanFilter" />
            </pivot:PivotViewer.PivotProperties>
        </pivot:PivotViewer>
        <Button HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,2,0,0" Width="100" Height="25" Content="Stop the Clock!" Click="Button_Click" />
    </Grid>
</UserControl>

Lastly let’s write some client code to create the sample set and bind it to our PivotViewer. Note that I’ve also written a rudimentary stopwatch that we’ll use to time when our PivotViewer is ready for a user to interact with it.

public partial class NoEfficiencies : UserControl
    {
        private const int SAMPLE_SIZE = 1000;

        private DateTime _start;

        public NoEfficiencies()
        {
            InitializeComponent();

            Loaded += (sender, e) =>
                {
                    var data = Person.GetSampleData(SAMPLE_SIZE);
                    _start = DateTime.Now;
                    pv.ItemsSource = data;
                };
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var timespan = TimeSpan.FromTicks(DateTime.Now.Ticks - _start.Ticks);

            MessageBox.Show(string.Format("Elapsed time is {0} seconds.", timespan.TotalSeconds.ToString()));
        }
    }
}

On my laptop it takes about 12 seconds for the items to appear in the PivotViewer.

So, what’s happening under the covers when we set the ItemsSource? First of all the control displays the Filter Panel on the left-hand side. This happens almost instantly and gives a good user experience. The delay is in producing the xaml tiles (or trading cards). This is because the runtime has to render static images from the databound markup. This is expensive.

Strategy 1: Use Pre-generated DeepZoom Images

You may have a situation where you can pre-build all your visuals and store them on a server. If you’ve spent any time working with PivotViewer v1 this will be very familiar territory. If your collections are going to be fairly static you can then just use the new CxmlCollectionSource class in combination with some dynamic features that I talked about in my previous post: Add, Remove & Change Cxml Items in PivotViewer.

Alternatively you can you the new PivotViewerMultiSizeImage control in your PivotViewerItemTemplates to render your pre-generated visuals. Either way, you’re swapping the cost of rendering the images from xaml with that of downloading them from the web.

Strategy 1 works well if your visuals are not very dynamic.

Strategy 2: Use Multiple Visual Templates

The PivotViewerItemTemplate I’ve used in my example is very inefficient for the number of tiles. Before I can interact with the control I have to wait for it to render 1000 tiles of information that I can’t possibly read at the default zoom level. So strategy 2 suggests defining multiple visual templates of increasing complexity. This helps by allowing the control to render simpler visual elements first and then the complex ones asynchronously. In the meantime, however, the user has been able to do some work.

            <pivot:PivotViewer.ItemTemplates>
                <!-- This new template will be shown up to a zoomed width of 100px -->
                <pivot:PivotViewerItemTemplate MaxWidth="100">
                    <StackPanel Orientation="Vertical" Height="75" Width="50" Background="LightGreen">
                        <TextBlock Text="{Binding Forename}" />
                        <TextBlock Text="{Binding Surname}" />
                    </StackPanel>
                </pivot:PivotViewerItemTemplate>
                <pivot:PivotViewerItemTemplate>
                    <StackPanel Orientation="Vertical" Height="150" Width="100" Background="LightBlue">
                        <TextBlock Text="{Binding Forename}" />
                        <TextBlock Text="{Binding Surname}" />
                        <TextBlock Text="{Binding Age}" />
                        <TextBlock Text="{Binding Sex}" />
                        <TextBlock Text="{Binding Address1}" />
                        <TextBlock Text="{Binding Address2}" />
                        <TextBlock Text="{Binding Address3}" />
                        <TextBlock Text="{Binding Address4}" />
                        <TextBlock Text="{Binding Postcode}" />
                    </StackPanel>
                </pivot:PivotViewerItemTemplate>
            </pivot:PivotViewer.ItemTemplates>

Once loaded, select an item by clicking on it. You’ll see the higher res template render as you zoom in. Now use the cursor keys to navigate. You’ll see flashes of green as new tiles come into view. Then, and only then, does the runtime render the higher res image.

Scenario 2 take about 8 seconds to load on my machine. 30% faster than our baseline!

Scenario 3: Stagger your loading

Hitting PivotViewer with 1000 items at once can be a bit overwhelming for it. It also means that your user has to wait until ALL 1000 items have been rendered before they can work. In the pre-beta versions of PivotViewer the team had investigated the idea of a BatchObservableCollection class. Unfortunately, this didn’t make it into the RC but we can still replicate the idea. Basically, we can drip feed batches of the whole over a period of time. If your scenario is very visual, this can be a really cool feature as the user gets to see data being assembled in front of them. Ultimately it takes more time, but might give your users the impression that it’s actually quicker!

First up, let’s add a new static method that will add items to an already existing collection.

public static void PopulateWithSampleData(ObservableCollection<Person> data, int sampleSize);

Next we’ll create a class that will handle the drip-feeding of the items. We need to specify an interval between batches so that a) PivotViewer thinks we’ve finished and starts to refresh the UI and b) so that the UI finishes its refresh before the next batch.

using System;
using System.Collections.ObjectModel;
using System.Windows.Threading;

namespace XamlTileEfficiency
{
    public class DripFeeder<T>
    {
        private readonly DispatcherTimer _timer;
        private readonly ObservableCollection<T> _data;
        private readonly int _sampleSize;
        private readonly int _batchSize;
        private readonly Action<ObservableCollection<T>, int> _populateAction;

        private int _counter;

        public DripFeeder(ObservableCollection<T> data, int sampleSize, int batchSize, TimeSpan interval, Action<ObservableCollection<T>, int> populateAction)
        {
            _timer = new DispatcherTimer { Interval = interval };
            _timer.Tick += _timer_Tick;

            _data = data;
            _sampleSize = sampleSize;
            _batchSize = batchSize;
            _populateAction = populateAction;
        }

        void _timer_Tick(object sender, EventArgs e)
        {
            _timer.Stop();

            if (_counter < _sampleSize)
            {
                // This won't take account of any remainders, but hey.
                _populateAction(_data, _batchSize);
                _counter += _batchSize;

                _timer.Start();
            }
        }

        public void Start()
        {
            _timer_Tick(null, EventArgs.Empty);
        }
   }
}

Now that we have all our building blocks we just need to change the client code from our baseline example like this. Notice that we do our databinding BEFORE we start to populate the collection.

            Loaded += (sender, e) =>
            {
                var data = new ObservableCollection<Person>();
                _start = DateTime.Now;
                pv.ItemsSource = data;

                var feeder = new DripFeeder<Person>(data, SAMPLE_SIZE, BATCH_SIZE, TimeSpan.FromSeconds(INTERVAL_SECONDS), Person.PopulateWithSampleData);
                feeder.Start();
            };

So, scenario 3 is great for situations where the gradual loading of data accompanied with the visual changes is OK. In public demos this might be impressive!

Scenario 4: Lazy Load your Facets

In combination with Scenario 2 this can be very powerful. It is also a great way to use PivotViewer with high-latency data. e.g. stuff gathered from multiple sources across the web. As long as our data items implement INotifyPropertyChanged we can lazy load the data asynchronously or triggered when we need it.

In this last example (LazyLoader.xaml) we’ll just load the Forename and Surname properties. Then, as the user selects items in the PivotViewer we’ll go and fetch the rest of the data. The control will handle the PropertyChanged events and re-render the visual elements for us. It’s not the most elegant example, but you should get the potential from it.

Wrap Up

The PivotViewer control is very powerful and flexible but you have to think about loading data in the right way for your situation. I’d love to hear of other scenarios that I haven’t covered here.

Finally, you can download the complete source code of the examples here.

 
11 Comments

Posted by on September 8, 2011 in PivotViewer

 

Tags: , , , ,