Subscribe


Add to Windows Live Add to Google
Add to My Yahoo Add to Bloglines Subscribe

Sponsors

The Silverlight Tour
Site hosting provided by:
Maximum ASP

Connect


Upcoming Appearances


Related Topics


Fun with ItemsControl

Silverlight Logo

I spend a bit of time on the Silverlight forums and I've noticed a trend recently. A number of people are trying to get the ListBox to behave like something other than a ListBox. Most often I find it when someone is trying to handle mouse effects for items in a DataTemplate in a ListBox. What's interesting about that is that many are surprised by the neat little ItemsControl control.

For example, here I have a small little Silverlight app that shows some XBox games in a scrollable horizontal list:

Notice that in this example I don't care about the 'selected' behavior and/or look and feel of the ListBox. I just want to display a series of items. I might want to do a pop-up when someone hovers over an item or even use things like hyperlinks in the items.  In these cases using a ListBox can become a problem because the ListBox wants to handle mouse events instead of handing them to me.  That's where the ItemsControl comes in.

The ItemsControl element is actually the base class of the ListBox and ComboBox so the API should be familiar:

<ItemsControl ItemsSource="{StaticResource theGames}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Border BorderBrush="Black"
              CornerRadius="10"
              BorderThickness="2"
              Margin="2"
              Padding="2"
              Background="#80000000">
        <StackPanel Width="150"
                    Height="150">
          <Image Source="{Binding ProductImageUrl}"
                 Height="100"
                 Width="80" />
          <TextBlock Text="{Binding ProductName}"
                     FontWeight="Bold"
                     FontSize="14" />
        </StackPanel>
      </Border>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

Notice the ItemsControl uses the same ItemsSource property and ItemTemplate that you're probably already using in your ListBox. Next we can use the ItemsPanel property to change the orientation of the control to be horizontal instead of vertical (notice the horizontal StackPanel that does this for us):

<ItemsControl.ItemsPanel>
  <ItemsPanelTemplate>
    <StackPanel Orientation="Horizontal"
                VerticalAlignment="Center"
                HorizontalAlignment="Center" />
  </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Lastly, we can surround it all with a ScrollViewer to give it the scrolling effect we might get from the ListBox:

<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible"
              ScrollViewer.VerticalScrollBarVisibility="Hidden">
  <ItemsControl ItemsSource="{StaticResource theGames}">
    <!-- ... -->
  </ItemsControl>
</ScrollViewer>

If your interested in how this all works together at runtime, go grab the source code and play around with it.  But take my advice and if you are looking for something similar to the ASP.NET Repeater control with a lot more power, grab the ItemsControl and go to town! 

Comments:

Gravatar

Shawn, your Silverliht application posted here loads 100% and does't nothing more. There is a problem? I follow you by Google Reader and your applications always apear there how I have not Silverlight plugin. Is this a issue?
http://tinyurl.com/9q743n

Gravatar

I wouldn't be surprised if the SL doesn't load right in Google Reader. If you go to the page on the site does it work? Also, what browser are you using? I didn't test it with multiple browsers. The real trick is to get the source code and play with it anyway.

Gravatar

Hi Shawn,

The app doesn't work on any of my browsers either. It stops at 100% loading progress. I am using IE 7.0.6001.18000 and FireFox 3.0.5 on a Windows Vista machine.

Lixin

Gravatar

Sorry, not sure what is wrong...it works on every browser i've tried it on.

Gravatar

Same error here.
Maybe the error message will help.
Line: 0
Error: Unhandled Error in Silverlight 2 Application String was not recognized as a valid DateTime. at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s)
at VideoGames.Gamelist..ctor()

Gravatar

That helps a great deal. Let me guess...you guys live on the other side of the GMT line (e.g. Europe or the Middle East)? I'll post a fix tommorrow...sorry for the confusion.

Gravatar

I've updated it to use US Culture (as I am Parsing Dates) so that should fix it for you. Sorry for my ethnocentric bug.

Gravatar

Thanks for educating us all on the differences

Gravatar

See my blog post on the bug and why you need to be aware of it for your own code:

http://wildermuth.com/2009/01/19/The_Culture_of_Silverlight

Gravatar

Thanks very useful example http://blogs.ugidotnet.org/davcup/archive/2009/01/20/quando-non-usare-listbox.aspx

Gravatar

Wow, that's cool stuff. I was just looking for something like the asp.net repeater yesterday and there it is - ready to use!

Gravatar

Thanks for saving me yet again:
http://www.wintellect.com/CS/blogs/rrobinson/archive/2009/01/22/yngwie-malmsteen-syndrome-silverlight-2-scroller-revisited.aspx

Gravatar

Do you have any suggestions for dealing with large item lists (8000+ items) in listbox or combobox? Seems like things choke as the list gets large. Does ItemsControl exhibit the same problems (10-20 seconds to display the listbox). A fast popup window to pick an items will be my next approach.

Gravatar

Bert,

You shouldn't fill the entire list with 8000 items. Some of the 3rd party controls (I think DevExpress but I can't remember) are virtualized which is how large lists are usually done.

Gravatar

How would you attach events to the ItemsControl to manage selection of the items themselves? That is, I would like to allow the user to click on the items and change a selection state (and change the selected item's visual appearance) <or> detect a left click and display a details panel over the underlying item.

Many thanks for advice

Gravatar

Matt,

If you want selection behavior you have two options. Use a ListBox instead (all these techniques work with anything that derives from ItemsControl including ListBox).

Alternatively, you could wrap your items in a UserControl so you can handle the behaviors.

Gravatar

is it possible to further customize the items control by disabling the horizontal scroll bar, and then moving the direction arrow buttons to either side of the images?

Gravatar

Donavan,

If you want to do that you could it with an ItemsControl, but normally I would do it with a clipping mask:

http://wildermuth.com/2007/08/31/Silverlight_Scrolling_Region_Example

Gravatar

I want selection behavior in my listbox (using what you had commented above) but for some reason it is not working as I would expect. I have a listbox bound to an observable collection and the datatemplate inside is being organized in a grid. This grid contains textblocks and buttons or check boxes. I am finding that the textblocks/buttons/check boxes are "blocking/masking" the ability to select the listboxitem itself, which I still need to be able to do and if I use the ishittestvisible property on the listboxitem (setting it to false) I can now no longer use buttons/checkboxes but I am able to select the listboxitem no matter where I click. Is there an elegant solution for my problem which would allow me to select the listboxitems no matter where I click and if I hit a checkbox/button that I will be able to do what the checkbox/button was intended for?

Gravatar

Over a year later and you've saved my bacon Mr Wildermuth. I was looking for a non selectable listbox in silverlight, this fits the bill nicely. Ta!

Gravatar

Hi Shawn,
In my Silver light application I have bind 30 "TabItem" to "ItemsControl".
Here I got one problem. I have applied "ShinyBlue" theme to Items control like following code

<Style TargetType="controls:TabItem" x:Key="MainTabItemStyle">
.
.
.
</Style>

While I click on TabItem my code is -

private void TabItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
TabItem _tabItem = sender as TabItem;
_tabItem.IsSelected = true;
}

Through this Selected tab item style was changed. If click another both first selected one and second one are in selected state.
How can I remove that style. I want the style for only select one. How can I remove for rest of 29 TabItems.


 



 
Save Cancel