开发者

Showing an IsBusy indicator on MainFrame when navigating between Silverlight pages

I am using the Silverlight 4 Navigation Framework and have pages that take some time to load (normally binding to large amounts of data).

I have put a IsBusy SL Toolkit control on the MainFrame and I want to set it to Busy when you click on the navigation to another page, and set it to NotBusy when the other page has finished loading.

To keep it simple and get it working first, I am excluding MVVM and just using code-behind calls, but my IsBusy 开发者_JAVA百科control never appears. I assume it is a UI threading issue but I need some help please.

EDIT: On a simple page, the IsBusy control IS appearing, but only once the requested page is loaded (and then it is turned off, hence you never see it). I need the calling page to invoke the IsBusy control on the parent frame and display it before it tried to even load the next page...

Here is the XAML on my MainFrame page:

   <Grid x:Name="LayoutRoot">
        <navigation:Frame
            x:Name="ContentFrame"... NavigationFailed="ContentFrame_NavigationFailed">
            <navigation:Frame.UriMapper>
                   ...
            </navigation:Frame.UriMapper>
        </navigation:Frame>

        <telerik:RadBusyIndicator
            x:Name="busyIndicator"
            BusyContent="Please wait..." />
    </Grid>

and here is the code on a page which navigates to another page:

    private void workorderButton_Click(object sender, RoutedEventArgs e)
    {
        ((MainPage) App.GetApp.RootVisual).busyIndicator.IsBusy = true;
        NavigationService.Navigate(new Uri("WorkOrderView", UriKind.Relative));
    }

and then on the destination page:

    public WorkOrderView()
    {
        InitializeComponent();

        ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = false;
    }

I've tried so many different options but the indicator never shows up. I tried wrapping it in some threading code and then it displayed but threw an invalid cross thread exception.

I tested the XAML using this code (a button on the same page) and it works fine (shows and hides):

    private void btnIsBusy_Click(object sender, RoutedEventArgs e)
    {
        ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = true;
        ThreadPool.QueueUserWorkItem((state) =>
        {
            Thread.Sleep(3 * 1000);
            Dispatcher.BeginInvoke(() => ((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = false);
        });
    }

I'm sure it's something to do with the UI thread... any help appreciated!

Thanks


I would recommend looking at the INavigationContentLoader interface introduced in Silverlight 4, which gives you a great place to hook into the navigation system and do things "globally" (across all navigations) like this.

See David Poll's blog post on doing something very simliar to this, here : http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation-revisited-for-silverlight-4-beta/

He happens to be doing something much more complex than you need (loading pages out of remote XAPs) but look at what he's doing with the BusyIndicator control, and hopefully it's fairly easy to see how to strip out and use just that piece (he provides source for all his stuff, so you can dig in as much as you like).

If that looks like more work than is necessary for your project, another way you might be able to accomplish it is to hook into Frame.Navigated and Frame.Navigating - create a Boolean property on the control hosting the Frame, set it to true in Frame.Navigating and back to false in Frame.Navigated and use data-binding to bind that Boolean property to your IsBusy control.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜