代码之家  ›  专栏  ›  技术社区  ›  Eddie Deyo

框架导航时如何显示加载图标?

  •  1
  • Eddie Deyo  · 技术社区  · 16 年前

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

    我有一个带有动画旋转圆(我称之为waiticon)的控件,我希望在加载帧时显示它,但它不会显示(即使它确实出现也不会旋转),因为UI线程被阻止加载帧的内容。我打不到电话 导航 在后台线程上,因为该框架属于UI线程。有没有方法在加载帧时显示waitIcon?可能是通过创建拥有waiticon的第二个线程?

    update——显示以下问题的示例代码:

    这是主窗口。我刚刚用一个动画椭圆来模拟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 回复  |  直到 16 年前
        1
  •  0
  •   Sergey Aldoukhov    16 年前

    启动时,主线程无法阻止WPF动画。故事板在它自己的线程中运行,渲染发生在WPF渲染线程中,这与主线程不同。另外,我认为框架的加载也是非阻塞的。

    所以你的代码还有别的问题,为什么不把它贴在这里让我们理解呢?

    编辑:关于故事板我错了。因为资源是在主线程上创建的,所以它在同一个主线程中运行。即使动态地创建故事板,它也无法从在主线程上创建的窗口中动态地创建对象。

    我对frame的看法是错误的——它在加载URL时阻塞了主线程。我总是使用WebBrowser控件,它是非阻塞的。

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

    • 如前所述,在不同的线程中创建带有动画的窗口 here .
    • 使用WebBrowser而不是框架。