See the question and my original answer on StackOverflow

Your code above does an upload so it cannot receive a DownloadProgressChanged event.

The rule is all a Download or Upload Async methods raise the corresponding Download or Upload progress changed events. Under the scene, UploadStringAsync is using the same code that UploadDataAsync is using (because a string is an array of bytes modulo the character encoding).

Non-async methods don't raise progress events.

If you want access to the underlying WebRequest, just create a class that derive from WebClient and override the protected virtual GetWebRequest(Uri address) method, like this:

public class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        // do something with the request
        // BTW, this is how you can change timeouts or use cookies
        return request;
    }
}

Note you can also use the more modern HttpClient class (which is fully cross platform, frameworks, etc.) instead of WebClient.