The AssemblyName Class

The other day, I was reading about the Assembly.FullName property, and I noticed this blurb:

Writing your own code to parse display names is not recommended. Instead, pass the display name to the AssemblyName constructor, which parses it and populates the appropriate fields of the new AssemblyName.

AssemblyName? I never knew about that! I checked it out, and it’s what you might expect: an assembly name parser. Here’s the example from MSDN:

using System;
using System.Reflection;

public class AssemblyNameDemo
{
   public static void Main()
   {
      // Create an AssemblyName, specifying the display name, and then 
      // print the properties.
      AssemblyName myAssemblyName = 
         new AssemblyName("Example, Version=1.0.0.2001, Culture=en-US, PublicKeyToken=null");
      Console.WriteLine("Name: {0}", myAssemblyName.Name);
      Console.WriteLine("Version: {0}", myAssemblyName.Version);
      Console.WriteLine("CultureInfo: {0}", myAssemblyName.CultureInfo);
      Console.WriteLine("FullName: {0}", myAssemblyName.FullName);
   }
}
/* This code example produces output similar to the following:

Name: Example
Version: 1.0.0.2001
CultureInfo: en-US
FullName: Example, Version=1.0.0.2001, Culture=en-US, PublicKeyToken=null
 */

Design-Time Data Binding in WPF

One of the cool things that WPF allows you to do is create sample data that can be bound to controls at design-time. This spiffy little feature allows you to do all kinds of tinkering with your UI without having to run your application. A short feedback loop is essential since WPF provides so much flexibility with what you can do. If you have an application that loads a significant amount of data, and you need to load all that data each time you want to see a UI change, that can lead to a significant amount of wasted time.

When you search for how to do this on the web, the most common method is to create a XAML file with your sample data, and then reference the file in the design data context. Here’s a very short example.

Spartan.cs

namespace adamprescott.net.DesignTimeDataBinding
{
    public class Spartan
    {
        public string Profession { get; set; }
        public byte[] Picture { get; set; }
    }
}

SpartanSampleData.xaml (Be sure to change BuildAction to DesignData!)

<m:Spartan xmlns:m="clr-namespace:adamprescott.net.DesignTimeDataBinding" 
           Profession="HooHooHoo">
</m:Spartan>

MainWindow.xaml

<Window x:Class="adamprescott.net.DesignTimeDataBinding.MainWindow"
        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"
        mc:Ignorable="d"
        d:DataContext="{d:DesignData Source=/SpartanSampleData.xaml}"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DockPanel VerticalAlignment="Top">
            <Image Source="{Binding Picture}" Height="50" />
            <TextBlock Text="{Binding Profession}" />
        </DockPanel>
    </Grid>
</Window>

I had a problem with this method, though. My model had a byte array property that stored image data, and I couldn’t come up with a good way to include a sample image in the design data XAML. I learned that you can also accomplish design-time data binding through the use of static classes, and that gave me exactly what I was looking for: the ability to create and define sample data in code! Here’s the same example as above, modified to use a static class.

SpartanSampleDataContext.cs (Note that I also added an image to the project in the root namespace.)

namespace adamprescott.net.DesignTimeDataBinding
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Windows;

    public static class SpartanSampleDataContext
    {
        public static Spartan SpartanSampleData
        {
            get
            {
                var result = new Spartan
                {
                    Profession = "HooHooHoo",
                    Picture = GetSampleImageBytes()
                };
                return result;
            }
        }

        private static byte[] GetSampleImageBytes()
        {
            var assemblyName = new AssemblyName(
                Assembly.GetExecutingAssembly().FullName);
            var resourceUri = new Uri(
                String.Format("pack://application:,,,/{0};component/leonidas.jpg", 
                assemblyName.Name));
            using (var stream = Application.GetResourceStream(resourceUri).Stream)
            {
                using (var memoryStream = new MemoryStream())
                {
                    stream.CopyTo(memoryStream);
                    return memoryStream.ToArray();
                }
            }
        }
    }
}

MainWindow.xaml

<Window x:Class="adamprescott.net.DesignTimeDataBinding.MainWindow"
        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"
        mc:Ignorable="d"
        xmlns:local="clr-namespace:adamprescott.net.DesignTimeDataBinding"
        d:DataContext="{x:Static local:SpartanSampleDataContext.SpartanSampleData}"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DockPanel VerticalAlignment="Top">
            <Image Source="{Binding Picture}" Height="50" />
            <TextBlock Text="{Binding Profession}" />
        </DockPanel>
    </Grid>
</Window>

See What Other Users Have Checked Out in TFS

There are lots of good reasons why you might want to identify which files are checked out by your fellow TFS users. Maybe you’re going to merge a branch and want to make sure everybody’s changes get included. Or perhaps an intern has gone back to school. Regardless of the reason, and whether you’re looking for all users or a specific user, it’s very easy to do!

If you’re a point-and-clickster, and you like working within the friendly confines of the Visual Studio IDE, you’ll be happy to know that there’s a menu option. Note this menu option is installed with the Visual Studio Team Foundation Server Power Tools, available from the Visual Studio Gallery.

  1. File > Source Control > Find in Source Control > Status…
  2. Find

But don’t fret if you’re a command-line purist, either. Microsoft’s got you covered with the tf status command. Here are some sample usages:

c:\tfs\tf status /user:*
c:\tfs\tf status /user:dave
c:\tfs\tf status c:\SomeOtherDir /recursive

Agile Story Points

User stories are one of the core concepts in agile software development. You need to build and maintain a prioritized backlog of estimated stories. Stories are accepted into an iteration from the top of the backlog during iteration planning, and the assigned resource becomes responsible and is held accountable to complete the story within the iteration.

One of the challenges with this process is estimating stories to ensure that they are scoped correctly to safely fit into and be completed within a single iteration. This is where story points enter the equation.

Story points are intended to provide a relative scale of effort for stories, but the unit of a story point is very open to interpretation and seems to vary throughout the community. To me, the most obvious unit for story points is hours. Others have suggested that you use a single, perfect day as the basis, or use a half-day. The problem I have with these suggestions is that there is an implicit conversion that occurs. And what about a story that will only take an hour or two? Days-as-points is too coarse.

Another suggestion I’ve heard is to use the simplest story you can think of as your points baseline. I like this idea. The problem is that I’d estimate the simplest story I can think of to take one hour, and then I’m right back to hours. Alternative units don’t seem to be alternative at all. Instead, I’m just doing extra math to abstract the numbers into something other than hours. At the end of the day, though, everything is still hours-based.

That’s how I felt about story points for a long time. I recently started thinking about story points in a slightly different way, and it’s working for me. Instead of converting to a different unit, I’ve been thinking about story points as an hours-based estimate that is equal parts effort, uncertainty, and complexity.

There are stories that I know will ultimately be fixed by a line or two of code, but they need some figuring-it-out time. The final effort required to complete the story is minimal since it’s probably just going to be a couple of lines. Assigning story points based on minimal effort that’s been adjusted to account for risk due to uncertainty and complexity works great. The story points estimate for this story will be comparable to a high-effort-but-simple, brute-force-type of story.

At the end of the day, the story points scale you and your team uses doesn’t matter as long as it works for you. You want your stories to have a story points estimate that indicates their total required effort, taking into account risk due to uncertainty and complexity. The team should feel good about accepting a story into the iteration and getting it done. You should be able to use the story point estimates from completed stories to determine your team’s velocity and predict future results.

Have you been down a similar path of enlightenment? What have you found that works or doesn’t work?

Software Developer Advice: Be Reputable!

If you want to have a successful career in software development, I have one very good piece of advice to offer: put your reputation above all else. I imagine this advice translates to other industries, but it’s certainly true in the world of software development. Here are some tips that you can use to help build and maintain a strong reputation as a developer.

Think like a user

Thinking like a user is a wonderful ability for a developer. When you add a piece of functionality, think to yourself, “How would I like this as a user?” Would you want to type in a file path? Probably not. You’d rather have some sort of browse capability that let’s you click through directories to find a file. Would you like browsing to an install directory, opening a config file, and editing XML to change a setting? Doubtful. You want to click a button or pick a menu option in the application to change settings.

I like to say that I “create software that works like software should,” and it’s all about thinking like a user. Users don’t want complicated, unintuitive solutions. They want something that is easy to use, does what it’s supposed to, and looks good. Think like a user, and create great products. Nothing will produce a better reputation than consistently producing great products!

Have higher standards than everybody else

Let’s say you–a customer–have low standards, and I–a developer–have “normal” standards. I give you an application that meets my normal standards. It has some minor bugs, but it’s generally functional. Since you have low standards, you’re probably happy with it, and we have good product satisfaction.

Now let’s say you have higher standards than me. I give you my same, normal-quality application. The previous flaws are now less acceptable, and satisfaction decreases. We get into a situation where satisfaction is mediocre. Easy-to-please customers like it, hard-to-please customers don’t.

If you hold yourself to a higher standard than everybody else, though, it’s likely that you’ll delight users more often than not. When a solution isn’t up to snuff, you need the courage and discipline to put the brakes on. Make sure it meets your standards before handing it off to others, and that brings me to my next point…

Ask for more time

Never, NEVER say development is done before you believe it is. I’ve had discussions with co-workers over the years that go like this: “Managers only care about closing projects. They don’t care about quality or doing it right.” It’s definitely true that managers care about closing projects, and rightfully so–you should, too! I don’t believe they want it happen at the expense of quality, though. If they do, they’re a bad manager, and you need to figure out how to make sure their bad managing doesn’t bring you down. I’d venture to say that 99.99% of managers and customers in the world will prefer a complete/good solution 2 weeks late over a partial/bad one delivered on time. So, when you need more time, you should ask for it.

There are some tricks to asking for more time, though. First and foremost, try to ask before you’ve actually run out of time. Everybody will be annoyed with you if they’re expecting a product on Monday and you tell them on Friday that it won’t be done. On the other hand, if you come to them two weeks before the deadline to request an extra week, it will likely be more well-received. And so comes the next trick: know how much time you need. You won’t be doing yourself favors by extending the deadline, and then extending it again, and then again. When you know you’re not going to finish on time, evaluate the work that needs to be done and estimate how much effort will be required. This will help in your explanation of why you need more time while simultaneously helping to ensure you ask for a sufficient amount of time.

Have integrity

I’m telling you that your reputation is the most important thing you have, but you should never try to protect or improve it by sacrificing honesty or integrity. If you make a mistake, own up to it, and grow from it. In fact, the bigger the mistake, the more important this becomes. Let’s say you introduce a bug that cripples your customers.  Clearly, it would be better to take action, letting everybody know about the critical issue and working to resolve it, rather than letting it be discovered on its own and inevitably traced back to you! Acknowledge that you made a mistake, and do whatever you can to help make it right.

Being open and honest will earn you the respect of your peers, your managers, and your customers. Treat others as you wish to be treated. When I’m asked a question, I answer to the best of my ability, providing accurate information–good or bad–along with relevant supporting details. I respond that way because that’s the type of response I hope to get when I ask a question. If you don’t provide accurate information, you’ll soon find that people don’t care what you have to say.

Closeable Tabs in WPF Made Easy

There are a number of good articles out there about creating closeable tabs in WPF, but they’re very complicated. It shouldn’t be that hard! So, I’m going to try to break it down and make it easy for you.

Here’s what we’re going to do:

  1. Create a new user control for the tab close button
  2. Create a new class that inherits from TabItem
  3. Try it out!

Create a new user control for the tab close button

Add a new UserControl to your project. Since it’s a full-blown UserControl, you can easily style the button however you’d like and add whatever additional code-behind logic you need. The important thing about the control is that it raises a “Close” event that can be handled in our custom TabItem control. You can get fancy with your button, but I wanted to keep it simple for this example so I just used a red button with a white X drawn on it.

XAML:

<UserControl x:Class="adamprescott.net.TabbedDocuments.TabCloseButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <Button Click="OnClick" Background="Red">
        <Path Data="M1,9 L9,1 M1,1 L9,9" Stroke="White" StrokeThickness="2" />
    </Button>
    
</UserControl>

Code-behind:

namespace adamprescott.net.TabbedDocuments
{
    using System;
    using System.Windows;
    using System.Windows.Controls;

    public partial class TabCloseButton : UserControl
    {
        public event EventHandler Click;

        public TabCloseButton()
        {
            InitializeComponent();
        }

        private void OnClick(object sender, RoutedEventArgs e)
        {
            if (Click != null)
            {
                Click(sender, e);
            }
        }
    }
}

Create a new class that inherits from TabItem

Add a new class to your project that derives from TabItem. My class has a single method, SetHeader. This method accepts the desired header content as an argument and adds it to a collection with our custom close button.

namespace adamprescott.net.TabbedDocuments
{
    using System.Windows;
    using System.Windows.Controls;

    public class CloseableTabItem : TabItem
    {
        public void SetHeader(UIElement header)
        {
            // Container for header controls
            var dockPanel = new DockPanel();
            dockPanel.Children.Add(header);

            // Close button to remove the tab
            var closeButton = new TabCloseButton();
            closeButton.Click +=
                (sender, e) =>
                {
                    var tabControl = Parent as ItemsControl;
                    tabControl.Items.Remove(this);
                };
            dockPanel.Children.Add(closeButton);

            // Set the header
            Header = dockPanel;
        }
    }
}

Try it out!

Now that all the hard stuff is done, let’s make a sample application to test it out. I have a simple Window with a Button and a TabControl. When the button is clicked, a tab is added with a TextBlock header and a TextBlock content. Each tab can be closed by clicking its close button.

XAML:

<Window x:Class="adamprescott.net.TabbedDocuments.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    
    <DockPanel>
        <Button DockPanel.Dock="Top" Click="OnPlusTabClick">+Tab</Button>
        <TabControl Name="uxTabs">
        </TabControl>
    </DockPanel>
    
</Window>

Code-behind:

namespace adamprescott.net.TabbedDocuments
{
    using System.Windows;
    using System.Windows.Controls;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnPlusTabClick(object sender, RoutedEventArgs e)
        {
            // Create the header
            var header = new TextBlock { Text = "Tab!" };
            
            // Create the content
            var content = new TextBlock
            {
                Text = string.Format("Tab numero {0}-o", 
                    uxTabs.Items.Count + 1)
            };

            // Create the tab
            var tab = new CloseableTabItem();
            tab.SetHeader(header);
            tab.Content = content;

            // Add to TabControl
            uxTabs.Items.Add(tab);
        }
    }
}

See? It didn’t have to be that hard!

Create a Button That Doesn’t Look Like a Button With WPF

One of my favorite things about WPF is that you can make controls look like anything you want. You want a button with text? <Button><TextBlock /></Button> You want a button with an image? <Button><Image /></Button>

So, when I was adding closeable tab functionality to my application, I figured it would be a breeze. When I added the button to the tab header, though, something undesirable happened: it looked like a button. I wanted a close button that just looked like an “X,” not the usual 3D Windows button. Luckily, this is easily accomplished through the use of control templates.

Creating a custom button is a two-step process:

  1. Create a ControlTemplate
  2. Apply the template

Here’s a short example of what I did to create a simple “X” close button:

<Window.Resources>
    <ControlTemplate x:Key="buttonTemplate" TargetType="Button">
        <Path Data="M0,0 L8,8 M8,0 L0,8" Margin="5,5,0,0" Stroke="Black" StrokeThickness="3" />
    </ControlTemplate>
</Window.Resources>

<Button Template="{StaticResource ResourceKey=buttonTemplate}" />

This works just fine, but I’ve created a usability problem. When the user sees or interacts with the button, there are no visual indicators that the item is clickable or anything happens when it’s clicked. No problems, though; we can fix these problems with a pair of style triggers.

<Window.Resources>
    <ControlTemplate x:Key="buttonTemplate" TargetType="Button">
        <Path Data="M0,0 L8,8 M8,0 L0,8" Margin="5,5,0,0" StrokeThickness="3">
            <Path.Style>
                <Style TargetType="{x:Type Path}">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="False">
                            <Setter Property="Stroke" Value="LightGray" />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Stroke" Value="Red" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Path.Style>
        </Path>
    </ControlTemplate>
</Window.Resources>

<Button Template="{StaticResource ResourceKey=buttonTemplate}" />

Now when you hover over the button, the X turns red. This is the perfect button for my closeable tab.

%d bloggers like this: