RIA Development Center
FeaturesTipsEventsVideosSilverlight GallerySilverlight Hosting Resources
Brad Abrams gives a brief overview of what Microsoft .NET RIA Services is and how it's going to make your life simpler. Read more
See more tips
Which platform do you use most often?
(Check one)
AIR
AJAX
Flash
JavaFX
Silverlight
Other

View Results
Get regular email alerts when we publish new features!
DevX RIA Development Update

More Newsletters
Leveraging Silverlight 2 with SQL Server and XML (cont'd)

Design Parameter Storage and Retrieval
Naturally you want every project to improve on any previous version so in this case we decided to add a feature which allows a user to save the parameters for a given design and then later to retrieve that design. Of course, the repository for these design parameters is a SQL Server database.

The database design to store the information required to permit a user to retrieve a stored imprint design is relatively simple. All that was needed was a single table which contained each of the various design parameters (product color, imprint color, font family, etc.)


Figure 5. SQL Server Table for Storing Design Parameters

Silverlight 2 Code for Popup Control

<!-- Popup to display stored links -->
<Popup x:Name="popDisplayStoredLinks">
    <Grid x:Name="grdDisplayStoredLinks" Background="#007799aa">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Border BorderBrush="Black" BorderThickness="2" Background="WhiteSmoke" 
CornerRadius="15" Grid.Column="1" 
Grid.Row="1">
            <StackPanel 
Margin="8" Width="330" >
                <StackPanel 
Orientation="Vertical">
                    <TextBlock 
Margin="5,5,0,5"  
HorizontalAlignment="Center" 
FontFamily="Comic Sans MS"  
                               FontSize="22" >
Saved Designs for </TextBlock>
                    <TextBlock 
x:Name="txbDisplayStoredLinksUserID" 
Margin="0,0,5,5" 
HorizontalAlignment="Center"  
                               FontFamily="Comic Sans MS"   
FontSize="22"  
Text="UserIDHere" />
                </StackPanel>
                <ListBox x:Name="lstSavedDesigns" SelectionChanged
="lstSavedDesigns_SelectionChanged" 
                         MouseLeftButtonUp="lstSavedDesigns_MouseLeftButtonUp" 
Margin="10" /> 
                <Button 
x:Name="btnPopCancelDisplayStoredLinks" 
Click="btnPopCancelDisplayStoredLinks_Click" 
                        Margin="5" 
Content="Cancel" Width="100" 
HorizontalAlignment="Center" VerticalAlignment="Bottom" />
            </StackPanel>
        </Border>
    </Grid>
</Popup>        }
//This popup window is triggered 
by setting its IsOpen property to true  

void webService_GetDesignsByUserIdCompleted(object 
sender, CustomerDesignsServiceReference.GetDesigns
ByUserIdCompletedEventArgs e)
{
    if (_dbOperationsStatus[e.UserState.ToString()] ==
_dbOperationStatus.Canceling)
    {
        _dbOperationsStatus[e.UserState.ToString()] = 
		_dbOperationStatus.Canceled;
    }
    else
    {
        try
        {
            RetrievalCircleAnimation.Stop();
            brdWaitAnimationRetrieveStoredLinks.Opacity = 0;
            m_dtDatabaseRetrievalTimeout.Stop();
            //Check to see how many results have 
			been returned
            //If no results, display an error message 
			in the existing form
            if (e.Result.Length < 1)
            {
                _dbOperationsStatus[e.UserState.ToString()] = 
                _dbOperationStatus.Selected;
                txbRetrieveStoredLinksResults.Text = "No artwork 
                found for UserID " 
               + txtRetrievalUserID.Text;
                btnRetrieveStoredLinksMaskClose.Content = "Close";
                return;
            }
            //If there is only one result, just display the 
                                        saved design immediately
            else if (e.Result.Length == 1)
            {
                _dbOperationsStatus[e.UserState.ToString()] = 
                _dbOperationStatus.Selected;
                RetrieveStoredLinksMask.Visibility = Visibility.Collapsed;
                popRetrieveStoredLinks.IsOpen = false;
                m_cdSavedDesigns = e.Result.ToList();
                DisplaySavedDesign(0);
            }
            else if (e.Result.Length > 1)
            {
                _dbOperationsStatus[e.UserState.ToString()] =  
                _dbOperationStatus.Selected;
                //If there are multiple results, save each record to a 
                CustomerDesign object and put a link in the 
                Display Stored Links popup
                RetrieveStoredLinksMask.Visibility = Visibility.Collapsed;
                m_cdSavedDesigns = e.Result.ToList();
                lstSavedDesigns.ItemsSource = m_cdSavedDesigns;
                lstSavedDesigns.DisplayMemberPath = "DesignName";
                popRetrieveStoredLinks.IsOpen = false;
                popDisplayStoredLinks.VerticalOffset = 
                (MainImageViewer.ActualHeight / 2) 
                - (174 / 2) + HeaderImage.ActualHeight - 25;
                popDisplayStoredLinks.HorizontalOffset = 
                (HeaderImage.ActualWidth / 2) 
                - (350 / 2);
                popDisplayStoredLinks.IsOpen = true;
                txbDisplayStoredLinksUserID.Text = e.Result[0].UserID.ToString();
            }
        }
        catch (System.Exception ex)
        {
            _dbOperationsStatus[e.UserState.ToString()] = _dbOperationStatus.Failed;
            txbRetrieveStoredLinksResults.Text = "An Error occurred while 
            retrieving your artwork. Please try again.";
            btnRetrieveStoredLinksMaskClose.Content = "Close";
            btnRetrieveStoredLinksMaskClose.Focus();
            Console.WriteLine(ex.Message);
        }
    }

Wait Animation
Since the process of communicating with a database located on a remote server is subject to the vagaries of the Internet, we decided to build a wait animation to request a user's patience while data is being saved or retrieved. A popular design these days for wait animations involves a series of circles themselves arranged in a circle. Each participating circle changes either its color or opacity in sequence with its partners, giving the effect of a Ferris wheel spinning around.

Figure 7.

Silverlight 2 Wait Animation

<!-- Wait Animation  -->
<Grid 
x:Name="RetrieveStoredLinksMask" Visibility="Collapsed"  >
    <Rectangle 
Fill="Black"  Opacity=".7"   RadiusX="13" RadiusY="13"/>
    <StackPanel  >
        <Border x:Name="brdWaitAnimationRetrieveStoredLinks" 
BorderThickness="0" 
BorderBrush="#FF000000" 
                Margin="0,40,0,20" 
Height="64" 
Width="64" >
            <Border.Background>
                <LinearGradientBrush 
EndPoint="0.5,1" 
StartPoint="0.5,0">
                    <GradientStop 
Color="#FF7A7777"/>
                    <GradientStop 
Color="#FF181717" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background> 
            <Grid  
ShowGridLines>="False" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition 
Width="Auto" />
                    <ColumnDefinition 
Width="Auto"/>
                    <ColumnDefinition />
                    <ColumnDefinition 
Width="Auto" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition 
Height="Auto" />
                    <RowDefinition 
Height="Auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Ellipse x:Name
="waitAnimationCircle1" Grid.Row
="3" Grid.Column="1"  
Grid.ColumnSpan="2"  
                         Margin="0,-10,0,0"  
Height="16" Width="16" Fill="White" />
                <Ellipse x:Name="waitAnimationCircle2" 
Grid.Row="1" 
Grid.Column="0" Margin="6,2,0,0"  
                         Height="16" 
Width="16" Fill="#FFA7A6A6" />
                <Ellipse x:Name="waitAnimationCircle3" 
Grid.Row="0" 
Grid.Column="1" 
Grid.ColumnSpan="2" 
                         Margin="0,0,0,-10" Height="16" 
Width="16" Fill="#FFA7A6A6" />
                <Ellipse x:Name
="waitAnimationCircle4" 
Grid.Row="1" 
Grid.Column="3" 
Margin="0,0,6,0" 
                         Height="16" 
Width="16" Fill="#FFA7A6A6" />
                <Ellipse x:Name
="waitAnimationCircle5" 
Grid.Row="2" 
Grid.Column="3" 
Margin="0,0,6,0" 
                         Height="16" 
Width="16" Fill="#FFA7A6A6" />
                <
Ellipse x:Name
="waitAnimationCircle6" Grid.Row="2" 
Grid.Column="0" 
Margin="6,2,0,0"  
                         Height="16" 
Width="16" Fill="#FFA7A6A6" />
            </Grid>
        </Border>
        <Border 
Background="White" 
CornerRadius="5" 
Margin="20" >
            <TextBlock 
x:Name="txbRetrieveStoredLinksResults"  
HorizontalAlignment="Center" 
TextWrapping="Wrap" 
Text="" 
                       Foreground="Black" 
TextAlignment="Center" />
         </Border>
        <Button x:Name="btnRetrieveStoredLinksMaskClose" Click
="btnRetrieveStoredLinksMaskClose_Click" 
                HorizontalAlignment="Center" Margin="20" 
Width="100" Content="Cancel"></ Button>
    </StackPanel>
</Grid><! 
--End of Wait Animation -->
//This wait animation can be started by calling its Begin() method
 and later stopped by calling its Stop() method. 
RetrievalCircleAnimation.Begin();
...
RetrievalCircleAnimation.Stop();

Building WPF/Silverlight animations is the forte of Expression Blend. In this case, the animation uses keyframes which change the color of the little circles to create the spinning effect. A useful technique for building an animation which will be incorporated into a much larger project is to create a separate Silverlight project with Blend and then once the animation has been refined, to transfer it into the main project.

Figure 8. Expression Blend Timeline for Wait Animation

Expression Blend Animation to Retrieve Designs Popup

<!-- Wait Animation for Retrieve Designs Popup -->
<Storyboard x:Name
="RetrievalCircleAnimation" 
RepeatBehavior="Forever" 
SpeedRatio=".25">
    <ColorAnimationUsingKeyFrames 
Storyboard.TargetName
="waitAnimationCircle6" 
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)"  BeginTime="00:00:00">
        <SplineColorKeyFrame KeyTime="00:00:00.1000000" Value="#FFFFFFFF"/>
        <SplineColorKeyFrame KeyTime="00:00:00.2000000" Value="#FFA7A6A6"/>
    </ColorAnimationUsingKeyFrames>
    <ColorAnimationUsingKeyFrames Storyboard.TargetName="waitAnimationCircle1" 
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)"  BeginTime="00:00:00">
        <SplineColorKeyFrame KeyTime="00:00:00.1000000" Value="#FFA7A6A6"/>
        <SplineColorKeyFrame KeyTime="00:00:00.6000000" Value="#FFFFFFFF"/>
    </ColorAnimationUsingKeyFrames>
    <ColorAnimationUsingKeyFrames 
Storyboard.TargetName="waitAnimationCircle2" 
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)" BeginTime="00:00:00">
        <SplineColorKeyFrame KeyTime="00:00:00.2000000" Value="#FFFFFFFF"/>
        <SplineColorKeyFrame KeyTime="00:00:00.3000000" Value="#FFA7A6A6"/>
    </ColorAnimationUsingKeyFrames>
    <ColorAnimationUsingKeyFrames 
Storyboard.TargetName="waitAnimationCircle3" 
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)"  BeginTime="00:00:00">
        <SplineColorKeyFrame KeyTime="00:00:00.3000000" Value="#FFFFFFFF"/>
        < SplineColorKeyFrame KeyTime="00:00:00.4000000" Value="#FFA7A6A6"/>
    </ColorAnimationUsingKeyFrames>
    <ColorAnimationUsingKeyFrames 
Storyboard.TargetName="waitAnimationCircle4" 
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)"  BeginTime="00:00:00">
        <SplineColorKeyFrame KeyTime="00:00:00.4000000" Value="#FFFFFFFF"/>
        <SplineColorKeyFrame KeyTime="00:00:00.5000000" Value="#FFA7A6A6"/>
    </ColorAnimationUsingKeyFrames>
    <ColorAnimationUsingKeyFrames 
Storyboard.TargetName="waitAnimationCircle5" 
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)" BeginTime="00:00:00">
        <SplineColorKeyFrame KeyTime="00:00:00.5000000" Value="#FFFFFFFF"/>
        <SplineColorKeyFrame KeyTime="00:00:00.6000000" Value="#FFA7A6A6"/>
    </ColorAnimationUsingKeyFrames>
</Storyboard>


Previous Page: Control Data Binding vs. Event Handling Next Page: Building a WCF Web Service
Page 1: Getting Started with Silverlight 2—the StepsPage 3: Design Parameter Storage and Retrieval
Page 2: Control Data Binding vs. Event HandlingPage 4: Building a WCF Web Service
Rate This Content:
Low     High
3 after 4 ratings