C# 如何在来自viewmodel的异步webclient调用中使用progressbar

C# 如何在来自viewmodel的异步webclient调用中使用progressbar,c#,mvvm,progress-bar,windows-phone-7.1,C#,Mvvm,Progress Bar,Windows Phone 7.1,我试图在WP7项目中使用performance progressbar,但在异步webclient调用方面遇到了问题。我的代码如下: 更新 public MainPage() { InitializeComponent(); ................... this.Loaded += new RoutedEventHandler(MainPage_Loaded);} private void MainPage

我试图在WP7项目中使用performance progressbar,但在异步webclient调用方面遇到了问题。我的代码如下:

更新

    public MainPage()
    {
        InitializeComponent();
         ...................

        this.Loaded += new RoutedEventHandler(MainPage_Loaded);}

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        if (!App.ViewModel.IsDataLoaded)
        {
            App.ViewModel.LoadData();
        }
    }
以及我实现LoadData功能的ViewModel

    private bool _showProgressBar = false;
    public bool ShowProgressBar
    {
        get { return _showProgressBar; }
        set
        {
            if (_showProgressBar != value)
            {
                _showProgressBar = value;
                NotifyPropertyChanged("ShowProgressBar");
            }
        }
    public void LoadData()
    {
        try
        {
            string defaulturl = "http://....";
            WebClient client = new WebClient();
            Uri uri = new Uri(defaulturl);
            client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
            ShowProgressBar = true;
            client.DownloadStringAsync(uri);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

        this.IsDataLoaded = true;

    }

    void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        try
        {
            //fetch the data
           ShowProgressBar = false;
        }

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {.....
    } 
主页Xaml

    <toolkit:PerformanceProgressBar Margin="0,-12,0,0" x:Name="performanceProgressBar" IsIndeterminate="true" Visibility="{Binding ShowProgressBar, Converter={StaticResource BooleanToVisibilityConverter}}"/>

我的问题是,因为WebClient在执行时是一个异步方法,所以LoadData已经执行,我无法确定将performanceProgressBar.Visibility放在何处


任何帮助都将不胜感激。谢谢

您只需返回UI线程--
Dispatcher
可以帮助您,我使用的一个常见代码片段(在我的ViewModelBase中是:

    protected delegate void OnUIThreadDelegate();
    /// <summary>
    /// Allows the specified deelgate to be performed on the UI thread.
    /// </summary>
    /// <param name="onUIThreadDelegate">The delegate to be executed on the UI thread.</param>
    protected void OnUIThread(OnUIThreadDelegate onUIThreadDelegate)
    {
        if (Deployment.Current.Dispatcher.CheckAccess())
        {
            onUIThreadDelegate();
        }
        else
        {
            Deployment.Current.Dispatcher.BeginInvoke(onUIThreadDelegate);
        }
    }

在你的评论中解释了更多之后,我了解了更多。听起来你想将布尔属性绑定到进度条的可见性。你需要一个布尔到可视性转换器(谷歌it,很容易找到)

然后你可以这样做:

private bool _showProgressBar = false;
public bool ShowProgressBar
{
    get { _return _showProgressBar; }
    set 
    { 
        _return _showProgressBar;
        OnPropertyChanged("ShowProgressBar");
    }
}

public void LoadData()
{
    try
    {
        string defaulturl = "http://....";
        WebClient client = new WebClient();
        Uri uri = new Uri(defaulturl);
        client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);

        ShowProgressBar = true;

        client.DownloadStringAsync(uri);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

    this.IsDataLoaded = true;

}

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    try
    {
        //fetch the data
        ShowProgressBar = false;
    }

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

}
关于这一观点:

<MyProgressBar Visibility={Binding Path=ShowProgressBar, Converter={StaticResource MyBoolToVisibleConverter}>


显然,MSFT已经为您提供了一个转换器……这对我来说是个新闻:

您希望如何使用“performanceProgressBar.Visibility”?您是否试图在加载开始时将其设置为可见,在加载完成时将其隐藏?也许我过于简化了您的问题,但为什么不在调用“client.DownloadStringAsync”之前将其设置为可见然后在async completed handler的末尾,只需将可见性设置为Hidden或Collapsed。重要的是,由于“completed handler”出现在另一个线程上,因此您必须将调用封送到GUI线程上,如下所述。因为DownloadStringAsync()在ViewModel中,我无法访问视图中的progressbar以更改其状态。我是否遗漏了某些内容?请查看下面的答案,我想我对您想要的内容有了更好的了解。您编写问题的方式听起来像是在代码中这样做,因此您可以访问progressbar。感谢您的回复。您能更具体地说明如何在我的代码中使用该代码段吗?我必须在客户端的viewmodel中实现它。\u DownloadStringCompleted()?尝试了一下,但是你可能需要调整/充实/做一些努力才能让它与你的解决方案的其余部分一起工作。嗯,我明白了。但是,正如我上面提到的,既然我已经在主页xaml上声明了progressbar控件,我怎么能从viewmodel访问它呢?我这里肯定遗漏了一些东西。好吧,你可以在上面引发一个事件您的viewmodel(在UI线程上),并让您的视图对此作出反应。我不知道我做错了什么,但不幸的是我无法找出问题所在。我使用了Coding4fun工具包中的BooleanToVisibilityConverter,但运气不佳:(那么,您还有什么问题?如果有错误,您会遇到什么错误?问题是progressbar没有隐藏。如果您希望看到更改,我已经更新了代码。ShowProgressBar值会按预期更改。但是我认为绑定和转换器出了问题。您的应用程序上还有其他属性吗绑定到您已验证的视图的视图模型正在视图上显示和更新?如果它们没有更新,您的视图模型是否实现INotifyPropertyChanged?这是通知视图它应该更新绑定值所必需的。
<MyProgressBar Visibility={Binding Path=ShowProgressBar, Converter={StaticResource MyBoolToVisibleConverter}>