Silverlight, WPF

A Small But Useful Tip

At work at the moment I am working on a large financial LOB app using WPF, where we regularly present the users with various information, some of which they can enter, and some of which they can not.

Now as you can imagine some of this data comes from a database, and as such database ID columns (Primary key values to be precise) are presented to the users. Now these IDs are highly important to our users (who just happen to be internal users within my company), but are obviously read only and database generated, and can grow quite large, as we have a lot of records of certain types of entities.

All following me so far I hope, well now we get to it, in an ideal world everything just works and no one cares about these IDs, and everyone goes about their business. But we are in the process of gradually improving this software (we do Agile iterations of improvements) so things change and occasionally things do go wrong, or do not work as expected, and our users generally relay this to us using the JIRA bug tracking software, where they can place screen shots, if they remember, or catch a problem in time, which quite often is not the case.

So on of those occasions where they do manage to get a screen shot and log it in JIRA that is extremely helpful, but when they do not, guess what is the most important bit of information they can give us.

That’s right we need to know the ID of they thing they were trying to take an action on, and obviously the type of thing they were trying to do at the time the problem occurred. Ok it might be logged, but it could have been an unlogged thing, we have not managed to foresee.

Now as I also mentioned these ID’s can get rather long, and its all too easy to write down the wrong number. I also mentioned that these ID’s are read only, so they are suited to Label type controls. Problem with using Labels is that  the user is unable to copy from them. Sounds a bit rubbish, we could use a ReadOnly TextBox but it just looks a bit naff, looks quite like a normal TextBox, which some users can’t see as being ReadOnly.

So what else can we do, well luckily with WPF we can simply create a TextBox style that makes a ReadOnly TextBox look like a Label, which now allows Copy into an email (say).

Now everyone is happy, we get the right ID sent to our JIRA bug tracking system, or an email, the UI still looks nice, and the TextBox is copy enabled.

Here is a small screenshot showing 3 TextBoxes

  1. A regular TextBox, problem is it allows user to enter Text. So that is out
  2. A ReadOnly TextBox, user can’t enter Text, but it looks like they can
  3. A Styled TextBox which is ReadOnly and looks like a Label and allows Copying from it. This is a winner I think

image

Here is the Style to make a ReadOnly TextBox look like a Label, that still allows copying from.

<Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="IsReadOnly" Value="true"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Border x:Name="Bd" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    SnapsToDevicePixels="true">
                    <ScrollViewer x:Name="PART_ContentHost" 
                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This post is not rocket science, but it may be useful to people that have similar requirements to me I hope.

 

Hope it helps

4 thoughts on “A Small But Useful Tip

  1. Nice tip, but to be true you could just remove all of this JIRA advertisement and simply replace the whole introduction with this:
    “Hey, this is how you create a label that allows copying of text. Simply use a ControlTemplate for a TextBox!”

  2. Nice tip, though personally I’d probably had settled with a “Copy to Clipboard” button. 🙂

    Just a few thoughts:

    1) As the border brush is transparent I would think the border thickness is uninteresting.
    2) AllowDrop really should be set to false i anything.
    3) ScrollViewer.PanningMode, not sure what this is, is it needed?
    4) Stylus.IsFlicksEnabled: I suppose this has a reason for being there, but as the box should contain all the information in one go I don’t think it’s needed.

  3. Nice job. I have to say though, I’d rather see this template applied dynamically through a trigger when ‘IsReadOnly’ is set. That’d be cool.

Leave a reply to Stimul8d Cancel reply