在 Silverlight 页面之间导航时在 MainFrame 上显示 IsBusy 指示器
我正在使用 Silverlight 4 导航框架,并且有些页面需要一些时间才能加载(通常绑定到大量数据)。
我在MainFrame上放置了一个IsBusy SL Toolkit控件,当您单击导航到另一个页面时,我想将其设置为Busy,并在其他页面加载完成时将其设置为NotBusy。
为了保持简单并首先让它工作,我排除了 MVVM 并仅使用代码隐藏调用,但我的 IsBusy 控件从未出现。我认为这是一个 UI 线程问题,但我需要一些帮助。
编辑:在一个简单的页面上,IsBusy 控件会出现,但只有在加载请求的页面后才会出现(然后它会被关闭,因此您永远不会看到它)。我需要调用页面来调用父框架上的 IsBusy 控件并在尝试加载下一页之前显示它...
这是我的 MainFrame 页面上的 XAML:
<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>
这是导航到另一个页面上的代码页面:
private void workorderButton_Click(object sender, RoutedEventArgs e)
{
((MainPage) App.GetApp.RootVisual).busyIndicator.IsBusy = true;
NavigationService.Navigate(new Uri("WorkOrderView", UriKind.Relative));
}
然后在目标页面:
public WorkOrderView()
{
InitializeComponent();
((MainPage)App.GetApp.RootVisual).busyIndicator.IsBusy = false;
}
我尝试了很多不同的选项,但指示器从未显示。我尝试将其包装在一些线程代码中,然后它显示出来,但引发了无效的跨线程异常。
我使用此代码(同一页面上的按钮)测试了 XAML,它工作正常(显示和隐藏):
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);
});
}
我确信这与 UI 线程有关...任何帮助表示赞赏!
谢谢
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 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我建议您查看 Silverlight 4 中引入的 INavigationContentLoader 接口,它为您提供了一个很好的位置来连接导航系统并像这样“全局”(跨所有导航)执行操作。
请参阅 David Poll 的博客文章,了解如何做与此非常相似的事情:http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation -revisited-for-silverlight-4-beta/
他碰巧正在做一些比您需要的更复杂的事情(从远程 XAP 加载页面),但是看看他使用 BusyIndicator 控件所做的事情,希望它是公平的很容易看到如何剥离和使用那部分(他提供了他所有东西的源代码,所以你可以根据自己的喜好挖掘)。
如果这看起来比您的项目所需的工作量更多,那么您可以完成它的另一种方法是挂钩 Frame.Naviged 和 Frame.Navigating - 创建一个托管 Frame 的控件上的布尔属性,在
Frame.Navigating
中将其设置为 true,并在Frame.Naviged
中将其设置回 false,并使用数据绑定将该布尔属性绑定到您的 IsBusy 控件。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
andFrame.Navigating
- create a Boolean property on the control hosting the Frame, set it to true inFrame.Navigating
and back to false inFrame.Navigated
and use data-binding to bind that Boolean property to your IsBusy control.