共用方式為


“Why didn’t you use a HyperlinkButton?”

The other day I was working on a Silverlight control that would display a taxonomy of categories.  Something along the lines of:

One > Two > Three > Four > Five

where “Five” is a child of the “Four” category, which, in turn, is a child of the “Three” category, and so on.  The way I initially though about it was that I would use a TextBlock for each of the categories and the “>” separators.  This actually worked fine.  Here’s a simple version of the XAML that I used:

     <StackPanel x:Name="LayoutRoot" Background="Black" 
                Orientation="Horizontal" Width="185" Height="15">
        <StackPanel.Resources>
            <Style x:Name="CategoryStyle" TargetType="TextBlock">
                <Setter Property="Foreground" Value="White" />
                <Setter Property="FontSize" Value="11" />
                <Setter Property="FontFamily" Value="Verdana" />
            </Style>
            <Style x:Name="SeparatorStyle" TargetType="TextBlock">
                <Setter Property="Foreground" Value="White" />
                <Setter Property="FontSize" Value="11" />
                <Setter Property="FontFamily" Value="Verdana" />
                <Setter Property="Margin" Value="3 0 3 0" />
            </Style>
        </StackPanel.Resources>
    </StackPanel>

And here’s the code:

     public void AddCategory(string categoryName)
    {
        TextBlock tb = new TextBlock();
        tb.Text = categoryName;
        tb.Style = this.CategoryStyle;
        tb.MouseEnter += new MouseEventHandler(OnMouseEnter);
        tb.MouseLeave += new MouseEventHandler(OnMouseLeave);
        this.LayoutRoot.Children.Add(tb);
    }

    private void OnMouseEnter(object sender, MouseEventArgs e)
    {
        TextBlock tb = (TextBlock)sender;
        tb.TextDecorations = TextDecorations.Underline;
    }

    private void OnMouseLeave(object sender, MouseEventArgs e)
    {
        TextBlock tb = (TextBlock)sender;
        tb.TextDecorations = null;
    }
     public void AddSeparator()
    {
        TextBlock separator = new TextBlock();
        separator.Text = ">";
        separator.Style = this.SeparatorStyle;
        this.LayoutRoot.Children.Add(separator);
    }

When I ran this it looked liked the following:

      taxonomy

And when you mouse over one of the categories, it underlines.  So I sent out my project for code review and one of the first comments to come back was: “Why didn’t you use a HyperlinkButton?”

Having never heard of the HyperlinkButton, I said, “There’s a HyperlinkButton?”  But I looked it up and indeed, not only was there a HyperlinkButton, but it had automatic underlining, so I no longer had to handle that myself.

So I changed the code to add HyperlinkButtons instead of TextBlocks.  This had the extra benefit of removing 12 lines of unnecessary code.  My new method looked like the following:

     public void AddCategory(string categoryName)
    {
        HyperlinkButton hb = new HyperlinkButton();
        hb.Content = categoryName;
        hb.Style = this.CategoryStyle;
        this.LayoutRoot.Children.Add(hb);
    }

and I was able to completely remove the OnMouseEnter() and OnMouseLeave() methods.  I left the seperators in as TextBlocks because they have no actions associated with them. 

Among other things, since HyperlinkButtons are Buttons, they expose the Click event so there is no need to handle the related Mouse and Keyboard events.