如何在viewmodel的异步webclient调用中使用progressbar

时间:2012-06-15 20:45:45

标签: c# mvvm progress-bar windows-phone-7.1

我正在尝试在WP7项目中使用性能进度条,但是我遇到了异步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)
    {.....
    } 

MainPage Xaml

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

我的问题是因为WebClient在执行时是一个异步方法,所以LoadData已经被执行了,我无法找出放置performanceProgressBar.Visibility的位置

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

2 个答案:

答案 0 :(得分:1)

在您的评论中解释了更多内容之后,我了解更多。听起来好像要将布尔属性绑定到进度条的可见性。你需要一个布尔到可见性转换器(google 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已经为您提供转换器......这对我来说是新闻:http://msdn.microsoft.com/en-us/library/system.windows.controls.booleantovisibilityconverter.aspx

答案 1 :(得分:0)

你只需要回到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);
        }
    }

然后可以简单地使用:

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    try
    {
        //fetch the data

        this.OnUIThread(() =>
        {
            performanceProgressBar.Visibility = Visibility.Collapsed; // This code will be performed on the UI thread -- in your case, you can update your progress bar etc.
        });

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

}