Question

I try to implement (in WPF, C#) Ellipse control which changes its colour depending on connection to google.com. If there is connection with Google, ellipse is green; else it's red.

I coded it this way:

XAML code

<Window.Resources>
    <l:InternetConnectionToBrushConverter x:Key="InternetConnectionConverter" />
</Window.Resources>
<Grid>
    <DockPanel LastChildFill="True">
        <StatusBar Height="23" Name="statusBar1" VerticalAlignment="Bottom" DockPanel.Dock="Bottom">
            <Label Content="Google connection:" Name="label1" FontSize="10" Padding="3" />
            <Ellipse Name="ellipse1" Stroke="Black" Width="10" Height="10" Fill="{Binding Converter={StaticResource InternetConnectionConverter}}" Margin="0,4,0,0" />
        </StatusBar>
    </DockPanel>
</Grid>

and C# behind-code (value converter and function checking connection):

public class InternetConnectionToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (targetType != typeof(Brush))
            throw new InvalidOperationException("The target must be a Brush!");

        return CheckConnection("http://www.google.com/") == true ? Brushes.Green : Brushes.Red;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    /// <summary>
    /// Checks connection to specified URL. 
    /// </summary>
    /// <param name="URL"></param>
    /// <returns><b>True</b> if there is connection. Else <b>false</b>.</returns>
    private bool CheckConnection(String URL)
    {
        try
        {
            HttpWebRequest request = WebRequest.Create(URL) as HttpWebRequest;
            request.Timeout = 15000;
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;

            return response.StatusCode == HttpStatusCode.OK ? true : false;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
            return false;
        }
    }

}


It works well but there are 2 problems:

  1. it takes some time to check connection, so I think I should be doing it in new thread (if I'm wrong, please tell me why)
  2. what's more important - it checks connection with Google only once, when program starts running (despite I use binding, so I expect that there would be constant connection monitoring)

How should I solve this?
I want to have constant connection monitoring, so that when I disconnect internet connection, Ellipse control will change its colour.

Was it helpful?

Solution

You must change your architecture a bit.
You can not use threading in an IValueConverter to avoid locking the UI. You still need to wait for the thread to complete before returning from the IValueConverter.

You need to create a HasConnection property to bind the ellipse color to. You can then run the connection check in another thread. Preferably by using the BackgroundWorker. The HasConnection property should be updated once the check is complete. You can then use a timer and check your connection periodically and update the HasConnection after each check.

Edit
You can also monitor the NetworkChange.NetworkAvailabilityChanged event to find out when local network connection goes up or down. However of you want to ensure that you can actually connect to your target you should keep your old CheckConnection, but call CheckConnection on startup, when the network availability changes and periodically on a timer.

OTHER TIPS

Use background worker to monitor in the background and ReportProgress to get the current status

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // Get the BackgroundWorker that raised this event.
    BackgroundWorker worker = sender as BackgroundWorker;

    bool connected = false;
    string url = "https://www.google.com/";

    while (!worker.CancellationPending)
    {
        try
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Timeout = 15000;
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;

            connected = (response.StatusCode == HttpStatusCode.OK);
            backgroundWorker1.ReportProgress(10, connected);
            Thread.Sleep(1000);

        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.ToString());
            e.Cancel = true;
            e.Result = "cancelled";

            //return false;
        }
    }
    e.Result = connected;
}

private void backgroundWorker1_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
    this.tbResult.Text = e.ProgressPercentage.ToString();
    System.Diagnostics.Debug.WriteLine(e.UserState.ToString());
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top