Scrolling with ease

This sample shows how to have animation while scrolling.

The UI is made up of a Grid with 3 columns with buttons for scrolling left and right and a listbox in the middle.

we are going to scroll horizontally 3 items at a time.
ListBox’s ItemsSource is set to a range of numbers 1-20

list1.ItemsSource = Enumerable.Range(1,20);

In the code we set up eventhandlers in page Loaded event along with a timer.
we have some variables to keep track of where we should stop scrolling. the most important variable is ‘easing’ which determines how fast or slow the animation will be. In the Timer_Tick event we change the horizontalOffset and when we reach the desired offset we stop scrolling

The code is not optimized and the values are hardcoded.
If there is another/better way of doing this sort of thing , please leave a comment

you can see a demo here and download source from here

Advertisements

Collpasing items in listbox

This sample shows how to animate the item in a listbox that is being deleted.
The sample would be lot cleaner, if Triggers , the ListBoxItem is exposed(instead of us keeping track of the items) and x:Static are supported
Note:Actual logic to delete which should be done after the animation is complete is not there
you can see a demo here and download source from here

Changing Itemtemplate to show details in when selected

There are places in which we want to show the details of an Item(ex. listboxitem) when it selected. As it is not easy to get the actual item(listbox item), we have to add some code to get a handle to the control when the controls are getting loaded

lets say we have this XAML


<UserControl x:Class=”SilverlightApplication10.Page”
    xmlns=”http://schemas.microsoft.com/client/2007
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
    Width=”400″ Height=”300″>
    <UserControl.Resources>
        <Style x:Key=”st1″ TargetType=”TextBlock”>
            <Setter Property=”Foreground” Value=”White”></Setter>
            <Setter Property=”FontFamily” Value=”Tahoma”></Setter>
            <Setter Property=”FontSize” Value=”12″></Setter>
        </Style>
        <DataTemplate x:Key=”dtContent”>           
                <ContentPresenter Width=”200″ x:Name=”cp” Loaded=”cp_Loaded”  ></ContentPresenter>                       
        </DataTemplate>
        <DataTemplate x:Key=”dt”>
            <StackPanel Background=”#333333″ Width=”200″ HorizontalAlignment=”Stretch”>
            <TextBlock Style=”{StaticResource st1}” Margin=”5,0,0,0″ Text=”{Binding FirstName}”></TextBlock>
                <StackPanel Margin=”5,0,0,0″ Loaded=”StackPanel_Loaded_1″ Visibility=”Collapsed”>
                    <TextBlock FontWeight=”Bold” Text=”Details:” Style=”{StaticResource st1}”></TextBlock>
                    <TextBlock Style=”{StaticResource st1}” Text=”{Binding Details}”></TextBlock>
                </StackPanel>
            </StackPanel>           
        </DataTemplate>
    </UserControl.Resources>
    <Canvas>
        <ListBox Canvas.Left=”50″ Canvas.Top=”50″     x:Name=”list1″ ItemTemplate=”{StaticResource dt}”>        
        </ListBox>
        <ListBox  Canvas.Left=”300″ Canvas.Top=”50″   x:Name=”list2″ ItemTemplate=”{StaticResource dtContent}” >
        </ListBox>
    </Canvas>
</UserControl>

In the first listbox initially we display just the firstname and when the item is selected we want to show additional details, we wrap the content that we want to be displayed only when it is selected in a panel and handle the loaded event to save a reference to it, so we can refer to it and toggle the visibility from ‘Collapsed’ to Visible’

List<StackPanel> _items = new List<StackPanel>();
private void StackPanel_Loaded_1(object sender, RoutedEventArgs e)
        {
            _items.Add(sender as StackPanel);
        }

void list1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (list1PreviousIndex > -1)
                _items[list1PreviousIndex].Visibility = Visibility.Collapsed;

            _items[list1.SelectedIndex].Visibility = Visibility.Visible;
            list1PreviousIndex = list1.SelectedIndex;
        }

The listbox on the left toggles the panels visibility when selected. the listbox on the right does the same thing, the only difference is the itemtemplate is actually a UserControl. we want to change the usercontrol when the listboxitem is displayed, for this we use ContentPresenter in the datatemplate, get a reference to it and change its contents

you can see a demo here and download source from here

Scrolling In ItemsControl

Here is one way to control a ScrollViewer without Scrollbar

Let say we have this basic UI 

A button on the left to scroll to the left, A button on the right to scroll right and ItemsControl between the buttons which is what we are going to scroll when the buttons are clicked

 <UserControl.Resources>
        <DataTemplate x:Key=”dt”>
            <TextBlock Margin=”5,0,0,0″ Text=”{Binding FirstName}”></TextBlock>
        </DataTemplate>
    </UserControl.Resources>
    <Canvas>
        <Grid Width=”400″ Height=”50″>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width=”50″></ColumnDefinition>
                <ColumnDefinition Width=”300″></ColumnDefinition>
                <ColumnDefinition Width=”50″></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Button Content=”left” x:Name=”btnLeft” Grid.Column=”0″></Button>
            <ScrollViewer Grid.Column=”1″ VerticalScrollBarVisibility=”Hidden” HorizontalScrollBarVisibility=”Hidden” x:Name=”sv” Width=”300″ Height=”50″>
                <ListBox  x:Name=”list1″ ItemTemplate=”{StaticResource dt}”>
                    <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation=”Horizontal”></StackPanel>
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>
                </ListBox>
            </ScrollViewer>
            <Button Content=”right” x:Name=”btnRight” Grid.Column=”2″></Button>
        </Grid>             
    </Canvas>

we hide the scrollbars of the scrollviewer and we have 2 buttons to scroll left and right. Lets  bind the listbox to an ItemsSource and attach eventhandlers to handle the buttonclick events


List<Customer> customers = new List<Customer>();
 for (int i = 0; i < 20; i++)           
    customers.Add(new Customer { FirstName = “Customer..” + i.ToString() });
           
 list1.ItemsSource = customers;
 btnLeft.Click += new RoutedEventHandler(btnLeft_Click);
 btnRight.Click += new RoutedEventHandler(btnRight_Click);

 

In the button click events we can change the ScrollToHorizontalOffset and HorizontalOffset  to get the desired effect


void btnRight_Click(object sender, RoutedEventArgs e)
        {
            if (sv.ScrollableWidth > 0)
            sv.ScrollToHorizontalOffset(sv.HorizontalOffset + 10);
        }

void btnLeft_Click(object sender, RoutedEventArgs e)
        {
            if (sv.HorizontalOffset > 0)
                sv.ScrollToHorizontalOffset(sv.HorizontalOffset – 10);
        }

 

 

Ratings control

This is a sample implementation for a ratings control. we can customize the shape by setting the template to something different. It defaults to stars but can be changed easily

Here are the sample templates used
 <Canvas Width=”600″
            Height=”600″>
        <local:RatingSelector Canvas.Left=”50″
                              Canvas.Top=”100″
                              Width=”200″
                              Height=”20″
                              MinRating=”1″
                              MaxRating=”4″>
            <local:RatingSelector.RatingTemplate>
                <ControlTemplate TargetType=”local:RatingItem”>
                    <Ellipse Width=”10″ Margin=”2″
                             Height=”10″
                             Fill=”{TemplateBinding Background}”
                             Stroke=”Black”
                             StrokeThickness=”1″>
                    </Ellipse>
                </ControlTemplate>
            </local:RatingSelector.RatingTemplate>
        </local:RatingSelector>
        <local:RatingSelector Canvas.Left=”50″
                              Canvas.Top=”150″
                              Width=”200″
                              Height=”20″
                              MinRating=”1″
                              MaxRating=”10″>
            <local:RatingSelector.RatingTemplate>
                <ControlTemplate TargetType=”local:RatingItem”>
                    <Path Margin=”2″
                          Stroke=”Gray”
                          StrokeThickness=”2″
                          Stretch=”Fill”
                          Fill=”{TemplateBinding Background}”
                          Data=”M 5,0 L 4,4 L 0,4 L 3,7 L 2,11 L 5,9 L 6,9 L 9,11 L 8,7 L 11,4 L 7,4 L 6,0″ />
                </ControlTemplate>
            </local:RatingSelector.RatingTemplate>
        </local:RatingSelector>
        <local:RatingSelector Canvas.Left=”50″
                              x:Name=”ctrl1″
                              Canvas.Top=”200″
                              Rating=”3″
                              Width=”200″
                              Height=”20″
                              MinRating=”1″
                              MaxRating=”5″></local:RatingSelector>
    </Canvas>

Update: The code will now work with Beta2  

you can see a demo here and download the source here