Given that Silverlight 3 can detect the online/offline status of the network, I thought I’d have a play with a simple control that displays something when the network is online and something else when the network is offline.
I started with a UserControl but ended up just with a Control using the “parts and states” model that had just one group of states called OnlineOfflineStates with 2 states within it named Online and Offline.
The source for the control is here and it’s just a little code ( might have bugs in it as it’s not been tried very much :-) );
namespace MikesControls
{
[TemplateVisualState(Name="Online", GroupName="OnlineOfflineStates")]
[TemplateVisualState(Name="Offline", GroupName="OnlineOfflineStates")]
[TemplatePart(Name="OnlineContentRoot", Type=typeof(Panel))]
[TemplatePart(Name="OfflineContentRoot", Type=typeof(Panel))]
public class OnlineOfflineControl : Control
{
public OnlineOfflineControl()
{
this.DefaultStyleKey = typeof(OnlineOfflineControl);
this.Loaded += OnLoaded;
}
void OnLoaded(object sender, RoutedEventArgs e)
{
DetermineNetworkStatus();
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged;
}
void DetermineNetworkStatus()
{
IsOnline = NetworkInterface.GetIsNetworkAvailable();
}
void OnNetworkAddressChanged(object sender, EventArgs e)
{
DetermineNetworkStatus();
UpdateOnlineOfflineUI();
}
public override void OnApplyTemplate()
{
onlineUI = base.GetTemplateChild("OnlineContentRoot") as Panel;
offlineUI = base.GetTemplateChild("OfflineContentRoot") as Panel;
base.OnApplyTemplate();
UpdateOnlineOfflineUI();
}
public static DependencyProperty IsOnlineProperty =
DependencyProperty.Register("IsOnline", typeof(bool), typeof(OnlineOfflineControl), null);
public bool IsOnline
{
get
{
return ((bool)base.GetValue(IsOnlineProperty));
}
internal set
{
base.SetValue(IsOnlineProperty, value);
}
}
public static DependencyProperty OnlineContentProperty =
DependencyProperty.Register("OnlineContent", typeof(object), typeof(OnlineOfflineControl), null);
public object OnlineContent
{
get
{
return (base.GetValue(OnlineContentProperty));
}
set
{
base.SetValue(OnlineContentProperty, value);
}
}
public static DependencyProperty OfflineContentProperty =
DependencyProperty.Register("OfflineContent", typeof(object), typeof(OnlineOfflineControl), null);
public object OfflineContent
{
get
{
return (base.GetValue(OfflineContentProperty));
}
set
{
base.SetValue(OfflineContentProperty, value);
}
}
void UpdateOnlineOfflineUI()
{
string state = IsOnline ? "Online" : "Offline";
VisualStateManager.GoToState(this, state, true);
}
Panel onlineUI;
Panel offlineUI;
}
}
and that goes hand in hand with a lump of XAML in the Themes/generic.xaml file;
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns:local="clr-namespace:MikesControls"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Style
TargetType="local:OnlineOfflineControl">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="local:OnlineOfflineControl">
<Grid
Background="{TemplateBinding Background}">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup
x:Name="OnlineOfflineStates">
<vsm:VisualState
x:Name="Online">
<Storyboard>
<DoubleAnimation
Duration="0"
Storyboard.TargetName="OfflineContentRoot"
Storyboard.TargetProperty="Opacity"
To="0.0" />
<DoubleAnimation
Duration="0"
Storyboard.TargetName="OnlineContentRoot"
Storyboard.TargetProperty="Opacity"
To="1.0" />
</Storyboard>
</vsm:VisualState>
<vsm:VisualState
x:Name="Offline">
<Storyboard>
<DoubleAnimation
Duration="0"
Storyboard.TargetName="OfflineContentRoot"
Storyboard.TargetProperty="Opacity"
To="1.0" />
<DoubleAnimation
Duration="0"
Storyboard.TargetName="OnlineContentRoot"
Storyboard.TargetProperty="Opacity"
To="0.0" />
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Grid
x:Name="OnlineContentRoot">
<ContentPresenter
Content="{TemplateBinding OnlineContent}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Grid>
<Grid
x:Name="OfflineContentRoot">
<ContentPresenter
Content="{TemplateBinding OfflineContent}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
and so the control ends up being;
- A template part called OnlineContentRoot which will, by default, show a ContentPresenter displaying the contents of a property called OnlineContent
- A template part called OfflineContentRoot which will, by default, show a ContentPresenter displaying the contents of a property called OfflineContent
- A couple of states – in the Online state we will display OnlineContentRoot and hide OfflineContentRoot and vice versa in the Offline state
that then means that I can use this control in a simple way by just setting the OnlineContent and OfflineContent as in;
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="clr-namespace:MikesControls;assembly=MikesControls" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
x:Class="OnlineOffline.MainPage">
<StackPanel>
<mc:OnlineOfflineControl
x:Name="onlineOffline">
<mc:OnlineOfflineControl.OnlineContent>
<TextBlock
FontSize="36"
Text="Online" />
</mc:OnlineOfflineControl.OnlineContent>
<mc:OnlineOfflineControl.OfflineContent>
<TextBlock
FontSize="36"
Text="Offline" />
</mc:OnlineOfflineControl.OfflineContent>
</mc:OnlineOfflineControl>
<Button
Content="Click Me When Online"
IsEnabled="{Binding ElementName=onlineOffline, Path=IsOnline}" />
</StackPanel>
</UserControl>
or perhaps;
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="clr-namespace:MikesControls;assembly=MikesControls" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
x:Class="OnlineOffline.MainPage">
<StackPanel>
<mc:OnlineOfflineControl
Width="192"
Height="192"
x:Name="onlineOffline">
<mc:OnlineOfflineControl.OnlineContent>
<Image
Source="/NetworkUp.png" />
</mc:OnlineOfflineControl.OnlineContent>
<mc:OnlineOfflineControl.OfflineContent>
<Image
Source="/NetworkDown.png" />
</mc:OnlineOfflineControl.OfflineContent>
</mc:OnlineOfflineControl>
<Button
HorizontalAlignment="Center"
Content="Click Me When Online"
IsEnabled="{Binding ElementName=onlineOffline, Path=IsOnline}" />
</StackPanel>
</UserControl>
which displays with these 2 icons (taken from here) when online/offline;
or the whole control can be re-templated by just dropping into Expression Blend and providing new values for the 2 parts OnlineContentRoot and OfflineContentRoot and then controlling the transitions between the states Online and Offline.
Posted
Mon, Apr 27 2009 4:17 PM
by
mtaulty