DCSIMG
Selectable Text Control - Windows DEV ices DEV
Sign in | Join | Help

Windows DEVices DEV

Elad Shaham's Blog

Selectable Text Control

image A few days ago we needed to allow selection of text in some of the fields in a read-only screen. This was required in order to apply copy and paste capabilities to those fields. About all of the fields on screen were shown using TextBlocks, which, as you may know, don’t allow selection of Text.

So after investigating this matter, we decided to replace all TextBlocks in fields that needed selection to TextBoxes with modified properties (no border, no tab stop, read only). We did have performance in mind, but could not think of a better solution. The solution looked something like this:

<TextBox Text="Hello" 
  IsReadOnly="True" 
  IsTabStop="False" 
  BorderThickness="0"
/>

But then a colleague of mine referenced me to this nice article about TextBoxes performance. Although the article writer and I did not share the same requirements, it did give me an idea of how to implement a solution with better performance. The idea was to change the TextBox template to host a simple TextBlock as long as the mouse cursor is not over the TextBox. Once the cursor moves over the TextBox, the template changes back to the default one. So now it looks like this:

<TextBox Text="Hello" 
  IsReadOnly="True" 
  IsTabStop="False" 
  BorderThickness="0"
  >
  <TextBox.Style>
    <Style TargetType="{x:Type TextBox}">
      <Style.Triggers>
        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition Property="IsMouseOver" Value="False" />
            <Condition Property="IsFocused" Value="False" />
          </MultiTrigger.Conditions>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type TextBox}">
                <TextBlock Text="{TemplateBinding Text}" />
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </MultiTrigger>
      </Style.Triggers>
    </Style>
  </TextBox.Style>
</TextBox>

 

This improves performance a lot, especially if you have quite a few of these controls spread around the screen. Using our dear friend Snoop, it’s very nice to see that the tree size changes from 10 (the original tree size of a TextBox) to 1:

Cursor not over

image

Cursor over

image

I'm still having issues with the layout of the different templates. Right now the text kinda jumps when the cursor goes over i, probably because of the complex layout of the default TextBox template. I did not find a way to make it work properly in all scenarios, if anybody got an idea that would be great!

Comments List

# re: Selectable Text Control

Published at Tuesday, July 07, 2009 12:31 AM by Maxim  

from my experience with forms (winforms + wpf):

if you have to put a lot of textboxes on form (and all should be visible) it will cost you in performance...

in your case: when all or most of text boxes must be in readonly state you can use textblocks/labels instead, if user wants to do some operation with some textblock/label he'll put focus on that control by mouse or by keyboard, in this case you'll do very simple trick: use only one textbox for emulation of editing process, in other words: when user clicks on desired textblock/label you show him a textbox above this control and this textbox will contain the text from textblock/label, when he'll finish editing, hide this textbox and update texblock/label underneath, you can move this textblock from one one textclock/label to other...

imagine excel sheet built with textboxes for each cell (creasy idea and bad performance); the solution is to enable edition of cell only when it focused. same is for datagrid and etc.

enjoy :)

# re: Selectable Text Control

Published at Tuesday, July 07, 2009 5:59 AM by Elad Shaham  

Well, I believe that your solution is in a way very similar to mine, only that in your case I would have to use c# code to move the only TextBox on the screen.

Aside from the fact that I have another constraint that I haven't mentioned - I can't use code behind, but only data templates, I also think that my solution is simpler. Using triggers to update the control template of the focused field is in my opinion cleaner than moving a TextBox around the screen as the cursor moves.

# re: Selectable Text Control

Published at Tuesday, July 07, 2009 9:35 PM by Maxim  

you're right, your solution is very useful and much better then mine...

but, if you'll need to do same thing in winforms 2.0, you don't have all nice things (templates, styles, etc) that you have in wpf...

# re: Selectable Text Control

Published at Wednesday, January 06, 2010 9:00 PM by Matt  

Very slick.  Thanks!

# re: Selectable Text Control

Published at Monday, April 12, 2010 12:39 PM by Albert  

Hi, thanks for the idea!

This is how you can avoid the jump effect of the text:

<TextBox Text="Hello" IsReadOnly="True"

IsTabStop="False" BorderThickness="0"

Grid.Column="0" Grid.Row="2"

Background="Transparent" TextWrapping="WrapWithOverflow">

<TextBox.Style>

<Style TargetType="{x:Type TextBox}">

<Style.Triggers>

<MultiTrigger>

<MultiTrigger.Conditions>

<Condition Property="IsMouseOver" Value="False" />

<Condition Property="IsFocused" Value="False" />

</MultiTrigger.Conditions>

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="{x:Type TextBox}">

<TextBlock Padding="3,1,3,1" Text="{TemplateBinding Text}" />

</ControlTemplate>

</Setter.Value>

</Setter>

</MultiTrigger>

</Style.Triggers>

</Style>

</TextBox.Style>

</TextBox>

# re: Selectable Text Control

Published at Monday, April 12, 2010 12:58 PM by Elad Shaham  

Yeah, I also played with a variation of your solution for the jump effect (I remember setting 3,1,3,1 for padding), but it did not work in all cases. I ended up implementing this scenario using attached properties.

# re: Selectable Text Control

Published at Monday, April 12, 2010 3:43 PM by Albert  

Would you be so kind to share it with us? ;)

# re: Selectable Text Control

Published at Monday, April 12, 2010 4:04 PM by Elad Shaham  

Unfortunately I can't - it's been a while and I have switched jobs, so I no longer have access to that code. I'll try to find the time to recreate it for a new post...

# re: Selectable Text Control

Published at Monday, April 12, 2010 5:10 PM by Albert  

Thanks anyway, no problem.

# re: Selectable Text Control

Published at Friday, May 07, 2010 7:52 PM by Rachel  

Thank you, this is the sort of thing I was looking for!

For me, I fixed the jumping text by adding Margin="2,0,2,0" and Padding="{TemplateBinding Padding}" to the TextBlock

# re: Selectable Text Control

Published at Thursday, March 22, 2012 8:57 PM by You're a douche with left flowing text!  

You're a douche with left flowing text!

# re: Selectable Text Control

Published at Thursday, March 22, 2012 11:44 PM by Elad Shaham  

Sorry, fixed

Leave a Comment

(required) 
(
required
)
 
(optional)
(required) 

Enter the numbers above: