Silverlight application can be designed in a way to work even in offline mode. Essentially Silverlight application is desktop based application running on client machine once downloaded from web server. Silverlight is capable to save data into local isolated storage area or upload data to WCF RIA service.
This control provide nice 3d led (Red and Green) and transitioning from red to green or vice-vera will occur when network status is changed.
The live application is available here : Live network indicator
The demo application also shows the smartkey (shortcut keys) navigation for silverlight, which i will post in Separate article alone with source code.
Xaml for the control is :
<Grid x:Name="LayoutRoot" Background="Transparent" > <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonState"> <VisualState x:Name="OnlineState"> <Storyboard> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OnlineElement" Storyboard.TargetProperty="(UIElement.Opacity)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <EasingDoubleKeyFrame KeyTime="00:00:01" Value="1"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OfflineElement" Storyboard.TargetProperty="(UIElement.Opacity)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1"/> <EasingDoubleKeyFrame KeyTime="00:00:01" Value="0"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OfflineElement" Storyboard.TargetProperty="(UIElement.Visibility)"> <DiscreteObjectKeyFrame KeyTime="00:00:00"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="00:00:01"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OnlineElement" Storyboard.TargetProperty="(UIElement.Visibility)"> <DiscreteObjectKeyFrame KeyTime="00:00:00"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="00:00:0.005"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="OfflineState"> <Storyboard> <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OnlineElement" Storyboard.TargetProperty="(UIElement.Visibility)"> <DiscreteObjectKeyFrame KeyTime="00:00:00"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="00:00:01"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OnlineElement" Storyboard.TargetProperty="(UIElement.Opacity)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1"/> <EasingDoubleKeyFrame KeyTime="00:00:01" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OfflineElement" Storyboard.TargetProperty="(UIElement.Opacity)"> <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/> <EasingDoubleKeyFrame KeyTime="00:00:01" Value="1"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="OfflineElement" Storyboard.TargetProperty="(UIElement.Visibility)"> <DiscreteObjectKeyFrame KeyTime="00:00:00"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> <DiscreteObjectKeyFrame KeyTime="00:00:00.005"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <StackPanel x:Name="OnlineElement" Orientation="Horizontal"> <Ellipse Margin="5" Height="15" Width="15" HorizontalAlignment="Left" VerticalAlignment="Center" > <Ellipse.Effect> <DropShadowEffect BlurRadius="8" Color="Black" ShadowDepth="0" /> </Ellipse.Effect> <Ellipse.Fill> <RadialGradientBrush> <GradientStop Color="#DB005400" Offset="0.977" /> <GradientStop Color="#E700FF00" Offset="0" /> <GradientStop Color="#FF275B00" Offset="0.773" /> </RadialGradientBrush> </Ellipse.Fill> </Ellipse> <TextBlock Text="Online" Foreground="White" FontWeight="Bold" VerticalAlignment="Center" Margin="2" Width="50"> <TextBlock.Effect > <DropShadowEffect BlurRadius="8" Color="White" ShadowDepth="2"/> </TextBlock.Effect> </TextBlock> </StackPanel> <StackPanel Visibility="Collapsed" x:Name="OfflineElement" Orientation="Horizontal"> <Ellipse Margin="5" Height="15" Width="15" VerticalAlignment="Center" > <Ellipse.Effect> <DropShadowEffect BlurRadius="8" Color="Black" ShadowDepth="0" /> </Ellipse.Effect> <Ellipse.Fill> <RadialGradientBrush> <GradientStop Color="#D5440000" Offset="1" /> <GradientStop Color="#E7FF0000" Offset="0" /> <GradientStop Color="#D07F0000" Offset="0.82" /> </RadialGradientBrush> </Ellipse.Fill> </Ellipse> <TextBlock Text="Offline" Foreground="White" FontWeight="Bold" VerticalAlignment="Center" Margin="2" Width="50"> <TextBlock.Effect > <DropShadowEffect BlurRadius="8" Color="White" ShadowDepth="2"/> </TextBlock.Effect> </TextBlock> </StackPanel> </Grid>
Code behind for the control is :
public partial class NetworkIndicator : UserControl { public NetworkIndicator() { InitializeComponent(); this.Loaded += new RoutedEventHandler(NetworkIndicator_Loaded); } void NetworkIndicator_Loaded(object sender, RoutedEventArgs e) { ResetNetworkStatus(); NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged); } void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) { ResetNetworkStatus(); } private void ResetNetworkStatus() { if (NetworkInterface.GetIsNetworkAvailable()) { VisualStateManager.GoToState(this, "OnlineState", true); } else { VisualStateManager.GoToState(this, "OfflineState", true); } } } }
The code can be further improved by using template based control and write an event to be raised when network status changes.