Control Data Binding vs. Event Handling
Although the XBAP project relied almost entirely on Data Binding to link changes in the text property of the user entry TextBoxes to the text property of the floating (imprint) TextBlocks, after studying this area, we concluded that at this early beta stage, data binding to control properties in Silverlight 2 was not yet practical for our purposes. (The current Silverlight version of Data Binding has neither an ElementName nor a Path property.) Instead, we used a series of event handlers which set the text property of each TextBlock equal to the text property of its corresponding TextBox.
| Editor's Note: For a walkthrough of databinding as it stands today in Silverlight, check out this tutorial on silverlight.net. |
Setting the Text Properties of a TextBlock
private void txtFirstName_TextChanged
(object sender, TextChangedEventArgs e)
{//When the user types into the First Name textbox,
add the same text in the First Name textblock
txbFirstName.Text = txtFirstName.Text;
PositionTextBlockInCanvas(txbFirstName);
//Adjust the location if it would fall
//outside the Imprint Area
If (txbFirstName.Text.Length == 0)
{//Also, unhide the And Character whenever the
//First Name textblock contains one or more letters
txbAndCharacter.Visibility = Visibility.Collapsed;
}
else
{
txbAndCharacter.Visibility = Visibility.Visible;
}
}
In this code sample, the Visibility property of the AndCharacter TextBlock is linked to the length of the Text property of the FirstName TextBlock. When there is no content in the FirstName TextBlock, the AndCharacter TextBlock is not visible but as soon as the user begins typing in the FirstName TextBox, the AndCharacter TextBlock is automatically set to Visible.
Changing the imprint color (Foreground property of the floating TextBlocks) is accomplished via event handlers. The MouseEnter event handler creates a SolidColorBrush which matches the color of the color rectangle currently beneath the cursor and then calls the ApplyNewImprintColorMethod.
Silverlight 2 Changing the Foreground Property of Floating TextBlocks
<!-- Colored rectangles representing Drink Mate standard imprint colors -->
<Rectangle x:Name="ImprintColorRectangle1"
Height="30" Width="30" Fill="#000000" Stroke="#FFFFFF" StrokeThickness="0"
MouseEnter="handleMouseEnterImprintColors"
MouseLeftButtonDown="handleImprintColorClick"
MouseLeave="handleMouseLeaveImprintColors" /><! --Black -->
<Rectanglex:Name="ImprintColorRectangle2"
Height="30"
Width="30" Fill="#000099"
Stroke="#FFFFFF"
StrokeThickness="0"
MouseEnter="handleMouseEnterImprintColors"
MouseLeave
="handleMouseLeaveImprintColors"
MouseLeftButtonDown
="handleImprintColorClick" /><! --Reflex Blue -->
<Rectangle x:Name="ImprintColorRectangle3"
Height="30" Width="30"
Fill="#0000CC"
Stroke="#FFFFFF"
StrokeThickness="0"
MouseEnter="handleMouseEnterImprintColors"
MouseLeave="handleMouseLeaveImprintColors"
MouseLeftButtonDown="handleImprintColorClick" /><! -- Medium Blue -->
<Rectangle x:Name="ImprintColorRectangle4"
Height="30" Width="30"
Fill="#3232FF" Stroke="#FFFFFF" StrokeThickness="0"
MouseEnter="handleMouseEnterImprintColors"
MouseLeave="handleMouseLeaveImprintColors"
MouseLeftButtonDown="handleImprintColorClick" /><! -- Process Blue -->
private void handleMouseEnterImprintColors(object
sender, MouseEventArgs e)
{
Rectangle rect = (Rectangle)sender;
SolidColorBrush newImprintColor = (SolidColorBrush)rect.Fill;
ApplyNewImprintColor(newImprintColor);
bdrTooltips.Visibility = Visibility.Visible;
txbTooltips.Text = "Click to change the imprint color.";
}
private void ApplyNewImprintColor(SolidColorBrush newImprintColor)
{
try
{
txbFirstName.Foreground = newImprintColor;
txbAndCharacter.Foreground = newImprintColor;
txbSecondName.Foreground = newImprintColor;
txbEventDate.Foreground = newImprintColor;
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
After the MouseLeave event occurs, the ApplyNewImprintColorMethod is called again to restore the imprint color to its currently selected value.
Drag and Drop
Different fonts have different metrics and when a user switches from font to font, the layout of the imprint information is not always optimal. To compensate for this we added the capability for a user to simply drag each floating TextBlock to a new location of his choice. Adding this drag and drop functionality under Silverlight 1.0 was a snap because all that was needed to do was to copy some code which we got from a Jesse Liberty video tutorial. Upgrading to Silverlight 2 was no more difficult because all we had to do this time was to copy and paste similar code from the Silverlight help files.
Silverlight 2 Text Drag and Drop
public void TextBlock_MouseDown(object sender, MouseEventArgs args)
{
TextBlock item = sender as TextBlock;
mouseVerticalPosition = args.GetPosition(null).Y;
mouseHorizontalPosition = args.GetPosition(null).X;
isMouseCaptured = true;
item.CaptureMouse();
}
public void TextBlock_MouseMove(object
sender, MouseEventArgs args)
{
TextBlock item = sender as TextBlock;
if (isMouseCaptured)
{
// Calculate the current position of the object.
double deltaV = args.GetPosition(null).Y
- mouseVerticalPosition;
double deltaH = args.GetPosition(null).X
- mouseHorizontalPosition;
double newTop = deltaV + (double)item.GetValue
(Canvas.TopProperty);
double MaxTop = cnvImprintArea.ActualHeight - item.ActualHeight;
double MaxLeft = cnvImprintArea.ActualWidth - item.ActualWidth;
//Put in some limitations to prevent a user from
//dragging a TextBlock outside the imprint area
if (newTop > MaxTop)
{
newTop = MaxTop;
}
if (newTop < 0)
{
newTop = 0;
}
double newLeft = deltaH +
(double)item.GetValue(Canvas.LeftProperty);
if (newLeft > MaxLeft)
{
newLeft = MaxLeft;
}
if (newLeft < 0)
{
newLeft = 0;
}
// Set new position of object.
item.SetValue(Canvas.TopProperty, newTop);
item.SetValue(Canvas.LeftProperty, newLeft);
// Update position global variables.
mouseVerticalPosition = args.GetPosition(null).Y;
mouseHorizontalPosition = args.GetPosition(null).X;
}
}
public void
TextBlock_MouseUp(object sender, MouseEventArgs args)
{
TextBlock item = sender as TextBlock;
isMouseCaptured = false;
item.ReleaseMouseCapture();
mouseVerticalPosition = -1;
mouseHorizontalPosition = -1;
}
Working with Custom Fonts
Wedding planners generally tend to use script-type fonts in their printing. While Silverlight 2 includes a number of attractive fonts, none of them is particularly suited to use with wedding designs. Fortunately, it is possible to include custom fonts with your Silverlight app by following these simple steps:
- Copy your custom fonts to the Client Bin folder for your Web Application (not the Client Bin folder for your Silverlight project)
- When referring to your custom fonts use the format [FileName]#[FontName] as, for example, brushscn.ttf#BrushScript BT
Silverlight 2 Working with Custom Fonts
//Using a custom font in Silverlight requires a combination of the filename
//along with the technical font name
string m_strAlexiCopperplate = @"alcoppln.ttf#Alexei Copperplate";
string m_strBrushScript = @"brushscn.ttf#BrushScript BT";
string m_strFlemishScript = @"flemscrn.ttf#FlemishScript BT";
string m_strFreestyle = @"frestysn.ttf#FreestyleScrD";
string m_strLinus = @"linusn.ttf#Linus";
string m_strParkAvenue = @"parkaven.ttf#ParkAvenue BT";
string m_strShelleyAllegro = @"shlyalln.ttf#ShelleyAllegro BT";
string m_strWeddingText = @"wedtxtn.ttf#WeddingText BT";
public void setFontFamilyProperty(string strFontFamily)
{
try
{
string strSelectedFontFamily;
switch (strFontFamily)
{//When a given case contains two entries,
the upper entry come from a selection in the combo box
//Lower entries come from saved designs
(some are identical, in which case only a
single entry is required)
case "Alexei Copperplate":
strSelectedFontFamily = m_strAlexiCopperplate;
break;
case "Brush Script":
case "BrushScript BT":
strSelectedFontFamily = m_strBrushScript;
break;
case "Flemish Script":
case "FlemishScript BT":
strSelectedFontFamily = m_strFlemishScript;
break;
case "Freestyle":
case "FreestyleScrD":
strSelectedFontFamily = m_strFreestyle;
break;
case "Linus":
strSelectedFontFamily = m_strLinus;
break;
case "Park Avenue":
case "ParkAvenue BT":
strSelectedFontFamily = m_strParkAvenue;
break;
case "Shelley Allegro":
case "ShelleyAllegro BT":
strSelectedFontFamily = m_strShelleyAllegro;
break;
case "Wedding Text":
case "WeddingText BT":
strSelectedFontFamily = m_strWeddingText;
break;
default:
strSelectedFontFamily = m_strAlexiCopperplate;
break;
}
txbFirstName.FontFamily = new FontFamily(strSelectedFontFamily);
txbAndCharacter.FontFamily = new FontFamily(strSelectedFontFamily);
txbSecondName.FontFamily = new FontFamily(strSelectedFontFamily);
txbEventDate.FontFamily = new FontFamily(strSelectedFontFamily);
//Display the message about Drag and Drop capability
bdrTooltips.Visibility = Visibility.Visible;
txbTooltips.Text = "Imprints can be repositioned by dragging.";
//Set a timer to hide the message about Drag and Drop
m_dtDragAndDropMessageTimer.Interval =
new
TimeSpan(0, 0, 0, 10, 0);
// 10 Seconds
m_dtDragAndDropMessageTimer.Tick += new
EventHandler(dtDragAndDropMessageTimer_Tick);
m_dtDragAndDropMessageTimer.Start();
}
Catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Using this same technique permits the drop down list of our custom combobox to preview the appearance of each custom font.
For more information on using Custom Fonts you can review this piece written by Tim Heuer. For a discussion of alternative delivery options, see this article by Rob Houweling.