Matt Casto's .NET Journal RSS 2.0
 Sunday, April 13, 2008

The TextBox control included with Silverlight 2 Beta 1 is a welcome addition.  There was no such control in previous versions of Silverlight, including the alpha.

Unfortunately, the TextBox control is very limited at this point.  It does not support scrollbars when it's content is larger than it's size.  You can "scroll" the next by moving the cursor, but that's just enough to make it functional.  Selecting text past what's visible doesn't automatically scroll to the cursor.  Also, there's no text wrapping, although setting the AcceptsReturn property to True will allow line breaks in the text.

I wanted to have a text box with a little more functionality for my projects, so I decided to see what I could do.  What follows is the simple ScrollingTextBox control that I created.  I didn't spend a ton of time on this because I fully expect this "missing" functionality to be included by Beta 2, or at least by the time Silverlight 2 is released.

 

To build this, I first created a Silverlight application project and added a Silverlight control called ScrollingTextBox.

<UserControl x:Class="PresentLight.ScrollingTextBox"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
    <ScrollViewer x:Name="sv" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
      <TextBlock x:Name="hiddenTextBlock" Opacity="0" />
      <TextBox x:Name="tb" AcceptsReturn="True" TextChanged="tb_TextChanged" />
    </ScrollViewer>
  </Grid>
</UserControl>

The internal TextBlock control is only there to serve as a way to get the actual size of the text.  TextBlock controls will automatically resize to fit their contents, so if I keep it's text the same as the internal textbox control, it will resize accordingly.  The default value for Width and Height dependency properties in Silverlight is Auto, which causes this resize behavior.

Since the ScrollViewer control automatically set's it's scrollable region to fit it's contents, it will be resized to fit the internal textblock.  The internal textbox control will automatically resize to fit it's container, since I haven't set any width or height on it.

Then I added a dependency property for setting the control's Text, which takes care of setting the textbox's text value.  Finally, I handled the TextChanged event on the internal TextBox control to resize based on my internal TextBlock's size.

using System.Windows;
using System.Windows.Controls;

namespace PresentLight
{
    public partial class ScrollingTextBox : UserControl
    {
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set
            {
                SetValue(TextProperty, value);
                tb.Text = value;
            }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), 
                               typeof(ScrollingTextBox), null);


        public ScrollingTextBox()
        {
            InitializeComponent();
        }

        private void tb_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (hiddenTextBlock != null)
            {
                hiddenTextBlock.Text = tb.Text;
                tb.Width = hiddenTextBlock.ActualWidth;
                tb.Height = hiddenTextBlock.ActualHeight;
            }
        }
    }
}

The result is a marginally better control.  There are a lot of possible improvements for me to make, such as possibly handing the selection changed event on the textbox to scroll the ScrollViewer to the cursor's position.  That will have to wait for a future post.

Sunday, April 13, 2008 9:41:18 AM (Eastern Standard Time, UTC-05:00)  #    Comments [2] -
silverlight
Tuesday, April 15, 2008 12:28:50 AM (Eastern Standard Time, UTC-05:00)
I tried this code, doesn't work.
It says : The property content is set more than once.

It allows only 1 line out of following 2 lines

<TextBlock x:Name="hiddenTextBlock" Opacity="0" />
<TextBox x:Name="tb" AcceptsReturn="True" TextChanged="tb_TextChanged" />

Any Idea why ? I am not able to compile


Ankit
Tuesday, April 15, 2008 7:14:28 AM (Eastern Standard Time, UTC-05:00)
I noticed the error in the XAML view in my project, but it compiles and runs for me.

This is very easy to fix. Just surround the TextBlock and TextBox with a Grid element.
Comments are closed.
Central Ohio Day of .NET

About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2008
Matt Casto
Sign In
All Content © 2008, Matt Casto
Theme based on DasBlog theme 'Business' created by Christoph De Baene (delarou)