在Frame导航时如何显示加载图标?

时间:2009-06-15 20:07:05

标签: wpf multithreading

我有一个带有Frame和TreeView的WPF应用程序。 TreeView显示我的应用程序的菜单,当单击一个项目时,框架通过调用Navigate显示该菜单项的内容。该调用有时需要几秒钟,导航完成时会阻止UI。

我有一个动画旋转圆圈的控件(我称之为WaitIcon),我想在框架加载时显示它,但它没有出现(并且即使它确实出现也不会旋转),因为UI线程被阻止加载Frame的内容。我无法在后台线程上调用Navigate,因为该帧由UI线程拥有。有框架加载时显示WaitIcon的方法吗?可能通过创建拥有WaitIcon的第二个线程?

更新 - 显示以下问题的示例代码:

这是主窗口。我刚刚使用动画Ellipse来模拟WaitIcon:

<Window x:Class="FrameLoadingTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <Storyboard x:Key="Animation" RepeatBehavior="Forever">
            <ColorAnimation From="Red" To="Black" Duration="0:0:2" Storyboard.TargetName="Ellipse1" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" />
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard Storyboard="{StaticResource Animation}" />
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="5*" />
        </Grid.ColumnDefinitions>
        <Button Click="Button_Click">Load Frame</Button>
        <Frame Name="ContentFrame" Grid.Column="1"></Frame>
        <Ellipse Name="Ellipse1" Height="100" Width="100" Visibility="Hidden" Fill="Red">
        </Ellipse>
    </Grid>
</Window>

按钮的点击事件:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Ellipse1.Visibility = Visibility.Visible;
    ContentFrame.Source = new Uri("TestPage.xaml", UriKind.Relative);
}

测试页:

<Page x:Class="FrameLoadingTest.TestPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="TestPage">
    <Grid>
        <TextBlock>Hello, world</TextBlock>
    </Grid>
</Page>

我在构造函数中进行了一次睡眠以模拟长时间运行的初始化:

public partial class TestPage : Page
{
    public TestPage()
    {
        InitializeComponent();
        Thread.Sleep(3000);
    }
}

在页面加载之前,椭圆不会显示。

1 个答案:

答案 0 :(得分:0)

WPF动画启动时,主线程无法阻止。故事板在其自己的线程中运行,并且渲染发生在WPF渲染线程中,该线程与主线程不同。另外,我相信Frame加载也是非阻塞的。

所以你的代码还有其他的东西,你为什么不在这里发帖,所以我们可以理解。

编辑:我在故事板上错了。由于资源是在主线程上创建的,因此它在同一主线程中运行。即使您动态创建了一个故事板,它也无法从主线程上创建的窗口中设置对象的动画。

我错了Frame - 它在加载URL时阻塞了主线程。我总是使用WebBrowser控件,它是非阻塞的。

所以,你有两个选择(可能更多,但我会列出两个):

  • 按照here所述的不同主题创建一个动画窗口。
  • 使用WebBrowser而不是Frame。