2010-07-13 3 views
3

Я использую это, чтобы сделать веб-запрос и загрузить некоторые данные:UI не обновляется в асинхронном веб-запроса обратного вызова

public partial class MainPage : PhoneApplicationPage 
{ 
    public MainPage() 
    { 
     InitializeComponent(); 

     var client = new WebClient(); 

     client.DownloadStringCompleted += (s, e) => { 
      textBlock1.Text = e.Result; 
     }; 

     client.DownloadStringAsync(new Uri("http://example.com")); 
    } 
} 

Текст textBlock1 никогда не меняется, даже если e.Result имеет правильные данные. Как мне обновить это из обратного вызова?

Edit: Если добавить MessageBox.Show(e.Result); в обратный вызов, наряду с назначением textBlock1.Text, как коробка messsage и текстовое поле показывают правильные данные.

Редактировать снова: Если я добавлю TextBox и задаю его текст сразу после строки textBlock1.Text, они оба отображают правильный текст.

+0

Я предполагаю, что там есть опечатка, ваш настоящий код: client.DownloadStringCompleted + = (s, e) => {textBlock1.Text = e.Result; }; правый? – TheTodd

+0

yup fixed. Благодарю. чрезмерно усердный backspacing :) –

+0

John - вне интереса переместите свой код в обработчик события «Loaded». Просто хочу посмотреть, не является ли это чем-то уникальным для конструктора. –

ответ

2

От просмотра через WP7 форумах, группа людей сообщали о том, что это было связано с вопросом драйвера видеокарты. Я обновил драйверы ATI Radeon HD 3400 до последней версии, и теперь он работает.

+1

По крайней мере, это означает, что он, скорее всего, будет работать на устройстве. Разочарование, хотя! –

1

client.DownloadStringAsync ожидает Uri, как это:

client.DownloadStringAsync(new Uri("http://example.com")); 

также, не вы должны обновить TextBlock через Dispatcher.BeginInvoke так:

client.DownloadStringCompleted += (s, e) => 
    { 
     if (null == e.Error) 
      Dispatcher.BeginInvoke(() => UpdateStatus(e.Result)); 
     else 
      Dispatcher.BeginInvoke(() => UpdateStatus("Operation failed: " + e.Error.Message)); 
    }; 
+0

Обновлен мой неправильный пример кода.Dispatcher.BeginInvoke может быть тем, что мне нужно. Я новичок WP7. Есть примеры? –

+0

Пробовал использовать Dispatcher.BeginInvoke, все еще не работал. Нет обновления. e.Result по-прежнему содержит правильные данные. –

+0

Я не думаю, что BeginInvoke должен быть необходим, потому что событие DownloadStringCompleted возникает в потоке пользовательского интерфейса. –

4

Я думаю, что это ошибка.

+0

Я начинаю думать так же. Я просто попробовал его с помощью приложения навигации WPF, и он работал нормально. –

1
public partial class MainPage : PhoneApplicationPage 
{ 
    public MainPage() 
    { 
     InitializeComponent(); 

     Loaded += MainPage_Loaded; 
    } 

    void MainPage_Loaded(object sender, RoutedEventArgs e) 
    { 
     var dispatcher = Deployment.Current.Dispatcher; 

     var client = new WebClient(); 

     client.DownloadStringCompleted += (s, e) => 
     { 
      var result = e.Result; 
      dispatcher.BeginInvoke(
       ()=> textBlock1.Text = result 
       ); 
     }; 

     client.DownloadStringAsync(new Uri("http://example.com")); 
    } 
} 
+0

Я попробовал пару разных комбо с Диспетчером, но я попробую снова и выясню, что другое. Спасибо, Дэниэл. –

+0

Пробовал. Тот же результат. Я думаю, что мы имеем дело с большей ошибкой, представленной в бета-версии. –

1

Я хочу прокомментировать, но еще не могу. Да, у меня очень похожая проблема. В моем случае это моя модель просмотра, которая обновляет свойство DownloadStatus, а затем, когда загрузка завершена, я делаю еще немного работы и продолжаю обновлять это свойство.

Вид перестает обновляться после того, как код ViewModel попадает в метод OpenReadCompleted. Я тщательно прошел через код. Свойство PropertyChanged, и представление даже возвращается и извлекает новое значение свойства, но никогда не показывает изменения.

Я был уверен, что это была ошибка, но затем я создал совершенно новый проект, чтобы воспроизвести проблему, и она отлично работает!

Вот фрагмент моего невоспроизводимого кода. Текстовый блок пользовательского интерфейса, привязанный к «DownloadStatus», счастливо обновляется должным образом на всем протяжении. Но та же парадигма не работает в моем основном проекте. Бешенство!

public void BeginDownload(bool doWorkAfterDownload) 
{ 
    DownloadStatus = "Starting ..."; 

    _doExtraWork = doWorkAfterDownload; 
    var webClient = new WebClient(); 

    string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("test:password")); 
    webClient.Headers["Authorization"] = auth; 

    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged); 
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted); 

    webClient.OpenReadAsync(new Uri("http://www.ben.geek.nz/samsung1.jpg")); 
} 

void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) 
{ 
    if (e.Error != null) 
    { 
     DownloadStatus = e.Error.Message; 
     return; 
    } 

    DownloadStatus = "Completed. Idle."; 

    if(_doExtraWork) 
    { 
     Thread t = new Thread(DoWork); 
     t.Start(e.Result); 
    } 

} 

void DoWork(object param) 
{ 
    InvokeDownloadCompleted(new EventArgs()); 

    // just do some updating 
    for (int i = 1; i <= 10; i++) 
    { 
     DownloadStatus = string.Format("Doing work {0}/10", i); 
     Thread.Sleep(500); 
    } 
    DownloadStatus = "Completed extra work. Idle."; 
    InvokeExtraWorkCompleted(new EventArgs()); 
} 
2

У меня также возникли проблемы с обновлением пользовательского интерфейса от разных диспетчеров. Что я наконец сделал, так это использовать собственный диспетчер TextBlock (или другой пользовательский интерфейс), и это сработало для меня. Я думаю, что в структуре телефона могут использоваться разные диспетчеры между приложением и элементами интерфейса. Обратите внимание на изменение от dispatcher.BeginInvoke к textbox1.Dispatcher ...

void MainPage_Loaded(object sender, RoutedEventArgs e) 
{ 
    var dispatcher = Deployment.Current.Dispatcher; 

    var client = new WebClient(); 

    client.DownloadStringCompleted += (s, e) => 
    { 
     var result = e.Result; 
     textBlock1.Dispatcher.BeginInvoke(
      ()=> textBlock1.Text = result 
      ); 
    }; 

    client.DownloadStringAsync(new Uri("http://example.com")); 
} 
Смежные вопросы