This page describes the implementation of the application.
For more information about the porting of the application can be found from the porting story page.
Reading the accelerometer information
The accelerometer is created on the member variable declaration:
protected Accelerometer m_Accel = new Accelerometer();
A handler for AccelerometerReadingChanged event is added and the sensor is started in the constructor.
// Set up the handler for accelerometer sensor data. m_Accel.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(AccelerometerReadingChanged); try { // Start the accelerometer sensor. m_Accel.Start(); } catch(AccelerometerFailedException exception) { MessageBox.Show("Failed to start the accelerometer sensor: " + exception.ToString()); }
In the event handler the event is dispatched for the UI thread and handled in the UpdateBubble method which calculates and updates the bubble position.
public void AccelerometerReadingChanged(object sender, AccelerometerReadingEventArgs e) { // Dispatch the accelerometer reading to UI thread Deployment.Current.Dispatcher.BeginInvoke(() => UpdateBubble(e)); }
Moving the bubble
In the XAML we define a TranslateTransform for the bubble image so that it will be easy to reference it on the C# code.
<!-- The Bubble image --> <Image Name="Bubble" Width="120" Height="60" HorizontalAlignment="Center" VerticalAlignment="Top" Stretch="Fill" Source="/BubbleLevel;component/gfx/bubble.png"> <!-- We give a name to the transform to easily move the bubble in the C# code --> <Image.RenderTransform> <TranslateTransform x:Name="BubbleTransform" /> </Image.RenderTransform> </Image>
In the C# code the transform is updated. In this case the Reflection is used to get the glass tube width.
// Set the bubble position. BubbleTransform.X = angle / MAX_ANGLE * (Reflection.Width / 2 - Bubble.Width / 2);
Implementing the flip animation
The flip animation is implemented into XAML as two Storyboard elements.
<Storyboard x:Name="SignFlipStoryBoard"> <DoubleAnimation Storyboard.TargetName="SignFrontProjection" Storyboard.TargetProperty="RotationX" To="90" Duration="0:0:0.125" /> <DoubleAnimation Storyboard.TargetName="SignBackProjection" Storyboard.TargetProperty="RotationX" To="0" Duration="0:0:0.125" BeginTime="0:0:0.125" /> </Storyboard> <Storyboard x:Name="SignResetStoryBoard"> <DoubleAnimation Storyboard.TargetName="SignBackProjection" Storyboard.TargetProperty="RotationX" To="-90" Duration="0:0:0.125" /> <DoubleAnimation Storyboard.TargetName="SignFrontProjection" Storyboard.TargetProperty="RotationX" To="0" Duration="0:0:0.125" BeginTime="0:0:0.125"/> </Storyboard>
The SignFlipStoryBoard will animate the the sign in two parts, first the front side of the sign is rotated by its x-axes for 90 degrees and continued by rotating the back side from its initial position -90 to 0. The Storyboard SignResetStoryBoard will animate the sign back by using just the opposite steps.
The Storyboards will animate the SignFrontProjection's and SignBackProjection's RotationX property. The first of them is defined in the XAML like this:
<!-- The front side of the sign --> <Image Width="504" Height="126" VerticalAlignment="Bottom" Margin="0,0,0,34" Visibility="Visible" MouseLeftButtonUp="FlipSign" Source="/BubbleLevel;component/gfx/signwithtext.png"> <!-- For flipping the sign --> <Image.Projection> <PlaneProjection x:Name="SignFrontProjection" /> </Image.Projection> </Image>
The starting of the animations are done in the C# code:
protected void ResetSign(object sender, MouseButtonEventArgs e) { SignResetStoryBoard.Begin(); }
Using the isolated storage to store calibration factor
The isolated storage is used to store the calibration factor when the Calibrate button is pressed. The calibration factor is restored on the application start.
The isolated storage is initialized on the member variable declaration, also we define a const string for the key to access the application setting and a member variable to store the value.
protected double m_CalibrationFactor = 0; protected IsolatedStorageSettings m_Settings = IsolatedStorageSettings.ApplicationSettings; protected const string CALIBRATION_SETTING_KEY = "CalibrationFactor";
The retrieving of the value is made in constructor:
// Read the calibration factor from isolated storage settings try { m_CalibrationFactor = (double)m_Settings[CALIBRATION_SETTING_KEY]; } catch (System.Collections.Generic.KeyNotFoundException) { // There did not exist settings yet. This is the first time that the application // is run on this device. }
And the saving is done in the Calibrate button's Click handler:
// Store the calibration factor to the isolated storage. if (m_Settings.Contains(CALIBRATION_SETTING_KEY)) { // The setting already exists, just update the value m_Settings[CALIBRATION_SETTING_KEY] = m_CalibrationFactor; } else { // The setting does not exist yet, create the setting m_Settings.Add(CALIBRATION_SETTING_KEY, m_CalibrationFactor); }
Release downloads
Attachments
-
BubbleLevelSilverlight.png
(380.5 KB) -
added by kratsan 12 months ago.

