2009-06-15 7 views
1

J'ai une application WPF avec un Frame et un TreeView. Le TreeView affiche le menu pour mon application, et quand un élément est cliqué, le cadre affiche le contenu de cet élément de menu via un appel à Navigate. Cet appel prend parfois plusieurs secondes et l'interface utilisateur est bloquée pendant la navigation.Comment afficher une icône de chargement lorsqu'un cadre navigue?

J'ai un contrôle avec des cercles de rotation animés (que j'appelle un WaitIcon) que je voudrais afficher pendant que le cadre charge, mais il n'apparaît pas (et ne tournerait pas même s'il apparaissait) parce que l'interface utilisateur thread est bloqué en chargeant le contenu du cadre. Je ne peux pas appeler Navigate sur un thread d'arrière-plan, car le cadre appartient au thread d'interface utilisateur. Y at-il un moyen d'afficher le WaitIcon pendant que le cadre se charge? Peut-être en créant un deuxième thread qui possède le WaitIcon?

MISE À JOUR - Exemple de code montrant le problème ci-dessous:

Voici la fenêtre principale. Je l'ai juste utilisé une animation Ellipse pour simuler le 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> 

L'événement de clic pour le bouton:

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

La page de test:

<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> 

Et je mets un sommeil dans le constructeur pour simuler une longue initialisation en cours d'exécution:

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

L'ellipse n'apparaît qu'après le chargement de la page.

Répondre

0

animation WPF, quand a commencé, ne peut pas être bloqué par le thread principal. Le storyboard s'exécute dans son propre thread, et le rendu se produit dans le thread de rendu WPF, qui est différent du thread principal. Aussi, je crois que le chargement de l'image est également non-bloquant.

Donc il y a quelque chose d'autre se passe avec votre code, pourquoi ne publiez pas ici afin que nous puissions comprendre.

EDIT: Je me suis trompé sur story-board. Comme la ressource est créée sur le thread principal, elle s'exécute dans le même thread principal. Et même si vous créez dynamiquement un storyboard, il ne pourra pas animer les objets à partir des fenêtres créées sur le thread principal.

Et je me suis trompé sur Frame - il bloque le thread principal lors du chargement d'une URL. J'ai toujours utilisé le contrôle WebBrowser, qui n'est pas bloquant.

Donc, vous avez deux options (peut-être plus, mais je vais énumérer deux):

  • Créer une fenêtre avec l'animation dans un thread différent comme décrit here.
  • Utilisez WebBrowser au lieu de Frame.
+0

J'ai mis à jour la question avec un échantillon –

Questions connexes