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
 Saturday, April 12, 2008

I haven't been posting much lately because I've been very busy preparing for my session at the Central Ohio Day of .NET.  I'm creating a presentation about Silverlight 2.0 Beta 1, but with a twist - the presentation is actually a Silverlight application!

Templates

For the last day or so I've been working on getting my application's main control to use templates to define the interface.  This gives me the option to create multiple "skins" for the application.

To accomplish this, I've been referencing two very excellent tutorials by Jesse Liberty and Shawn Burke.  But, as usual for me, I ran into a problem that sucked up a ton of time.

The Problem

I was trying to set up my template to include buttons for navigation between slides.  I started by building a simple XAML interface for the buttons, like so.

<StackPanel Orientation="Horizontal">
    <Button Height="75" Width="75" Margin="0,0,8,0">
        <TextBlock Text="First" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Button>
    <Button Height="75" Width="75" Margin="0,0,8,0">
        <TextBlock Text="Prev" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Button>
    <Button Height="75" Width="75" Margin="0,0,8,0">
        <TextBlock Text="Next" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Button>
    <Button Height="75" Width="75">
        <TextBlock Text="Last" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Button>
</StackPanel>

 

And that looks good enough for this example.

 

Then I took that same XAML and put it into a template stored in the application resources (in App.xaml).

<Application.Resources>
  <Style x:Key="TestTemplate" TargetType="pl:Presentation">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="pl:Presentation">
          <StackPanel Orientation="Horizontal">
            <Button Height="75" Width="75" Margin="0,0,8,0">
              <TextBlock Text="First" HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Button>
            <Button Height="75" Width="75" Margin="0,0,8,0">
              <TextBlock Text="Prev" HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Button>
            <Button Height="75" Width="75" Margin="0,0,8,0">
              <TextBlock Text="Next" HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Button>
            <Button Height="75" Width="75">
              <TextBlock Text="Last" HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Button>
          </StackPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Application.Resources>

And modified my Page.xaml to have my Presentation UserControl class (modeled after Shawn Burke's tutorial) with the template applied as a style.

<local:Presentation x:Name="PresentationControl" Style="{StaticResource TestTemplate}" />

But running this treated me to a browser window that's stuck loading.  My break point in OnApplyTemplate in my Presentation class never got hit.  Pausing Visual Studio didn't tell me anything, so I knew it wasn't stuck in a loop.  This had me stuck for several hours.

The Solution

What I eventually found was that certain things that are perfectly acceptable XAML in a user control won't work in a template.  Furthermore, if Silverlight encounters these elements in the template it just hangs.

The problem XAML was the buttons.  Instead of including your actual buttons in your template, you should instead create a separate template for the buttons, and reference that as your button style.

<Style x:Key="TestButton" TargetType="Button">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Button Width="75" Height="75">
          <Button.Content>
            <ContentPresenter Content="{TemplateBinding Content}" 
                              HorizontalAlignment="Center" 
                              VerticalAlignment="Center" />
          </Button.Content>
        </Button>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Then modify the previous template to use the new button template.

<Application.Resources>
  <Style x:Key="TestTemplate" TargetType="pl:Presentation">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="pl:Presentation">
          <StackPanel Orientation="Horizontal">
            <Button x:Name="FirstButtonElement" Content="First" 
                    Style="{StaticResource TestButton}" Margin="0,0,8,0" />
            <Button x:Name="PreviousButtonElement" Content="Prev" 
                    Style="{StaticResource TestButton}" Margin="0,0,8,0" />
            <Button x:Name="NextButtonElement" Content="Next" 
                    Style="{StaticResource TestButton}" Margin="0,0,8,0" />
            <Button x:Name="LastButtonElement" Content="Last" 
                    Style="{StaticResource TestButton}" />
          </StackPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Application.Resources>

Finally, this works.  It looks the same, but now I can take the template and make it look much nicer if I want.

Hopefully this tip will help others working on templating in Silverlight avoid the pitfalls I ran into.

Saturday, April 12, 2008 5:45:08 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1] -
silverlight
 Thursday, March 06, 2008

In Windows XP's Add/Remove Programs you get information about installed applications such as copyright, version, last run, etc.  At first glance this information appears to be gone in Windows Vista's Programs and Features.

Where'd the Program Information Go?

I was recently trying to figure out the version of Silverlight that I have installed, but selecting the item from Programs and Features doesn't tell me anything.  Also, clicking Uninstall immediately starts the uninstallation without showing me the version, and clicking Change didn't do anything at all.

I was thinking to myself, "Microsoft wouldn't just remove this information totally ... that would be stupid," so I spent a little more time poking around and found that you can right click on the column headers, click on More... and get a dialog that allows you to select other columns to display.

Programs and Features - Choose Columns

The information that used to be available by default in Add/Remove Programs is now displays in these columns.  It sucks that it's apparently hidden from view, but I guess it didn't take me too long to find it.

Loading

Another change in Programs and Features is the loading.  Add/Remove Programs could take a long time to display, but once it did you had everything available.  Programs and Features loads installed applications bit by bit, and refreshes the screen.  This is annoying if you've started scrolling down or selected an item before its done loading, because the refresh causes things to jump around.

While its nice that it loads a lot quicker in Vista, it almost appears to be worse because it punishes you for trying to use it too quickly.  This reminds me of how Windows boots a lot more quickly in XP and Vista, but it does more things after you've logged in so the system really isn't available immediately.  If you click on the Start menu too quickly it will go away.  Again, punishing you for working too quickly.

I'd like an OS that keeps up with how fast I want to work.

Thursday, March 06, 2008 10:19:08 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1] -
misc
 Wednesday, March 05, 2008

I arrived at work this morning only to find that the Silverlight 2.0 Beta 1 plugin and some documentation was discovered and available for download.  A few hours later the SDK and documentation was available, then after the keynote at Mix that whole lot was officially released.  I couldn't wait to try it out when I got home.

Unfortunately, the install experience hasn't been good.  I've got the Silverlight 2.0 plugin and SDK installed, but I can't get the tools for Visual Studio 2008 installed.  Here's step by step what I've done so far.

  1. Downloaded and installed the Silverlight 2 Beta 1 plugin (runtime) without a hitch.
  2. Downloaded Silverlight 2 Beta 1 SDK, Silverlight 2 Beta 1 Tools for Visual Studio 2008, and Expression Blend 2.5 March Preview.
  3. Uninstalled Silverlight 1.1 Alpha Tools for Visual Studio 2008 and Expression Blend 2 December Preview.
  4. Installed Silverlight 2 Beta 1 SDK.
  5. Tried to install Silverlight 2 Beta 1 Tools for Visual Studio but got the following error message:
    1. An Error Has Occurred:
      Silverlight Tools cannot be installed because one or more of the following conditions is true:

      1. Visual Studio 2008 RTM is not installed.
      2. The Web Authoring feature of Visual Studio is not installed.
      3. A previous version of the Silverlight Runtime is installed.
      4. A previous version of the Silverlight SDK is installed.
      5. The Visual Studio Update KB949325 is installed.
      6. A previous version of Silverlight Tools is installed.

      To continue, please install or uninstall the appropriate products and run this installer again.

  6. Verified what I had installed.  I've got Visual Studio Team System 2008 RTM, Microsoft Visual Studio Web Authoring Component, Silverlight runtime, Silverlight 2 SDK, Silverlight 1.0 SDK.  Oops, maybe that's the problem?  Also, I didn't uninstall Silverlight 1.1 Alpha runtime before installing Silverlight 2.0 runtime, but that shouldn't be a problem.
  7. Uninstalled Silverlight runtime and both SDKs, then rebooted for good measure.
  8. Installed Silverlight runtime, 2.0 SDK, ran silverlight_chainer.exe again and got the same error.
  9. Did a web search and found http://blog.steeleprice.net/archive/2008/03/05/1362.aspx which mentions a registry key that needs to be removed, but I don't have that registry key on my system.

At this point I can't find any more information through web searches or in the Silverlight.Net forums.  I'm posting this problem in the forums with a link here for a complete description of the problem.

I was really hoping to get few things done in Silverlight 2.0 and posted online tonight, but I'm kind of stuck and frustrated at this point.

UPDATE

Chad Campbell responded to my Silverlight.net forum post with a solution.  The solution definitely isn't something that I'd say is obvious, but hey, do whatever works.  I'm just a little surprised that I'd have more trouble with the beta than the alpha.

A big thanks goes out to Chad for his quick reply.  I'm definitely going to have to buy his book now!

Oops!

Even though the tools are now installed, something is still wrong.  Here's what I get when I try to create a Silverlight project in Visual Studio 2008.


Resolution

It turns out that the Silverlight 2 Tools Beta 1 for Visual Studio 2008 installs the Silverlight 2 Beta 1 runtime and SDK as part of the package.  This causes a problem if you already installed the plugin or the SDK.  I uninstalled everything Silverlight related, then installed silverlight_chainer.exe, this time successfully.  I'm now ready to go.

Wednesday, March 05, 2008 9:56:34 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
betas | silverlight
 Friday, February 29, 2008
I just got into a nerd fight with another developer on my team about which style of LINQ join syntax looks better.

Normally I wouldn't be one to get too worked up about syntax differences like this, but in this case my code was changed from one to the other for no reason other than "I don't like the way your wrote it."

Which do you prefer?



or


Friday, February 29, 2008 3:29:42 PM (Eastern Standard Time, UTC-05:00)  #    Comments [10] -
programming
 Thursday, February 21, 2008
I had to response to my soon-to-be-former boss' post about how an architect packs when moving offices.

A Silverlight guy could pack today with some great looking boxes that work with all major moving trucks, but they won't really hold all of his stuff.  They're kind of like those XAML boxes, but with huge gaps.  He feels the need to defend his box choice when compared with the competitor's boxes, which have been in production for years and total market penetration.

The Silverlight guy would rather wait another month or so, for the 2.0 beta of the box.  This version will solve all of his packing needs, can be loaded 1000 times faster than other common boxes and comes with a license allowing it to be used immediately.  The 2.0 boxes will also feature data cateloguing, content memory, multiple languages and can be used to build even better composite boxes.  So the Silverlight guy will probably wait until after the big conference when the new box is supposed to be announced.

Thursday, February 21, 2008 9:12:15 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] -
silverlight
 Sunday, January 20, 2008
I haven't stayed on top of this blog because I've been so busy with so many different things that taking time to write a post seems to be far down on the priority list.  I'm not going to say that will change this year, because that's almost cliche, but some of the things on my goal list will naturally lead to some posts here.

CodeMash

CodeMash v2.0.0.8 was awesome.  There have already been so many other blog posts talking about how great it was, so I'm not going to go into detail.  I'll sum it up by saying that it was totally worth it, and I'd be insane to miss it next year.

Resolutions

I have some goals for 2008, but really only one resolution.  My resolution is to do the push-up a day challenge.  But I decided to also do a sit-up per day, and throw in jumping jacks to toss in some cardio.  Today I've done 20 of each.  As the year moves on and things get harder, I may have to only do the exercises every other day, in order to give my muscles a chance to recover.


Goals for 2008
  • Present at at least 2 technical user groups
  • Write at least 2 articles for established websites
  • Contribute to a well known open source project
  • Create a fun game in Silverlight and host it at CodePlex
  • Create a custom layout for this blog and port it to SubText

Wow, that's a lot, but I already have one user group talk scheduled.  Should be a fun year.
Sunday, January 20, 2008 9:13:42 AM (Eastern Standard Time, UTC-05:00)  #    Comments [1] -
blog | codemash | misc
 Friday, December 21, 2007
I haven't posted in a long time, not because I haven't wanted to, but because I've been spending every minute of my free time working on a Session Scheduler application for CodeMash.

I can now talk about it because it's gone live!

The session scheduler was written in Silverlight 1.1 Alpha.  I would have written it in Silverlight 1.0 but I really wanted to be able to use Isolated Storage.  With Isolated Storage I was able to make the application store any changes the user makes locally, so the next time you go to the site it will be exactly where you left it and retain any of the sessions you've scheduled.

Using the Session Scheduler

The default view of the scheduler shows all sessions and Wednesday.  Unfortunately I didn't get around to implementing some sort of scrolling for the session list, but it was low on the list of features since the typical view of the application only has 6-8 sessions being shown at once.

You can click on the track buttons in the upper left to filter the session list by that track, or you can click on a session slot on the right (the agenda) and the session list will filter based on which sessions are available for that time of the day.

If you hover over a session menu item the session's details will drop down.  From that view, the green button can be used to schedule that session in your agenda.  Just hovering over the button will automatically show the time slot in the agenda where that session will occur.  Also, clicking on the speaker's name will show the speaker's bio.  This will show a picture of the speaker soon, but I'm having an issue displaying images in there at the moment.

You can click on the link image in the upper right to get a URL that can be used to send your custom agenda to someone else.  Currently, if you view another person's custom agenda it will overwrite any changes you've made yourself.  A workaround for this would be to copy a link to your agenda first, then use it once you're done looking at the other user's agenda.  I'm currently working on modifying this to save a history of agendas that you've looked at.

You can view my schedule here. ;-)

You can also click on the email image to view a simple HTML page with your custom agenda allowing you to print or email it from there.

I will be following up this post with several more describing the roadblocks I hit, and how I resolved, or worked around, them.

Friday, December 21, 2007 8:42:59 AM (Eastern Standard Time, UTC-05:00)  #    Comments [2] -
codemash | silverlight
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)