2010-01-27 4 views
0

J'ai une application où lorsqu'une personne tape ou sélectionne une zone de liste, une partie de l'écran est mise à jour dynamiquement vers une nouvelle vue. Le problème est que depuis WPF exécute tout dans un seul thread l'affichage de la vue peut interférer avec la saisie ou la navigation rendant l'application moins sensible. Ce que je voudrais faire est d'exécuter la partie vue dans un fil différent. Ma première pensée a été d'utiliser une fenêtre fonctionnant sur un thread différent, mais plus que d'être un peu un hack, il y a le problème de la fenêtre perdant le focus et d'être placé derrière la fenêtre principale quand on clique sur la fenêtre principale. Je pourrais le faire le plus en haut mais j'ai aussi besoin de placer d'autres fenêtres en face de lui.WPF Cadre dans un filetage séparé?

Alors, quel est le meilleur moyen d'y parvenir, puis-je placer la vue dans un cadre et l'exécuter dans un fil différent?

Répondre

1

Vous pouvez charger/générer les données dans un thread backround, puis mettre à jour l'interface utilisateur à l'aide de Dispatcher.BeginInvoke.

0

Je vous propose d'utiliser la propriété Visibilité de cette partie de l'écran que vous souhaitez faire apparaître et d'utiliser un déclencheur pour le rendre Invisible ou Réduit à Visible à chaque fois que l'utilisateur tape ou sélectionne. Ou vous pouvez animer la propriété Opacité pour produire un effet d'évanouissement cool ;-) Je vais ajouter du code pour illustrer le point. EDIT: un temps BackgroundTask, comme les opérations de fichiers, peut être réalisé en utilisant un BackgroundWorker

<Window x:Class="VisibleOnTypingSpike.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"> 
<StackPanel> 
    <StackPanel Orientation="Horizontal"> 
     <Label Name="TypingSnooper" 
       Visibility="{Binding TypingSnooperVisibility}"> 
      You are typing!</Label> 
     <Label> 
      <Label.Style> 
       <Style> 
        <Setter Property="Label.Opacity" Value="0"/> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding HasListBoxNewSelection}" Value="True"> 
          <DataTrigger.EnterActions> 
           <BeginStoryboard > 
            <Storyboard> 
             <DoubleAnimation From="0" To="1" 
                 Duration="0:0:1" 
                 Storyboard.TargetProperty="Opacity"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </DataTrigger.EnterActions> 
          <DataTrigger.ExitActions> 
           <BeginStoryboard > 
            <Storyboard> 
             <DoubleAnimation From="1" To="0" 
                 Duration="0:0:1" 
                 Storyboard.TargetProperty="Opacity"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </DataTrigger.ExitActions> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </Label.Style> 
      You selected! 
     </Label> 
    </StackPanel> 
    <TextBox TextChanged="TextBox_TextChanged"></TextBox> 
    <ListBox Name="SimpleListBox" 
      SelectionChanged="SimpleListBox_SelectionChanged"> 
     <ListBoxItem>1</ListBoxItem> 
     <ListBoxItem>2</ListBoxItem> 
    </ListBox> 
</StackPanel> 

using System.Windows; 
    using System.Windows.Controls; 

namespace VisibleOnTypingSpike 
{ 
    public partial class Window1 : Window 
    { 
     public Visibility TypingSnooperVisibility 
     { 
      get { return (Visibility)GetValue(TypingSnooperVisibilityProperty); } 
      set { SetValue(TypingSnooperVisibilityProperty, value); } 
     } 

     public static readonly DependencyProperty TypingSnooperVisibilityProperty = 
      DependencyProperty.Register("TypingSnooperVisibility", 
             typeof(Visibility), 
             typeof(Window1), 
             new UIPropertyMetadata(System.Windows.Visibility.Collapsed)); 

     public bool HasListBoxNewSelection 
     { 
      get { return (bool)GetValue(HasListBoxNewSelectionProperty); } 
      set { SetValue(HasListBoxNewSelectionProperty, value); } 
     } 

     public static readonly DependencyProperty HasListBoxNewSelectionProperty = 
      DependencyProperty.Register("HasListBoxNewSelection", 
             typeof(bool), 
             typeof(Window1), 
             new UIPropertyMetadata(false)); 

     public Window1() 
     { 
      InitializeComponent(); 
      DataContext = this; 
     } 

     private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
     { 
      var textbox = (TextBox) sender; 
      if (textbox.Text.Length > 0) TypingSnooperVisibility = Visibility.Visible; 
      else TypingSnooperVisibility = Visibility.Hidden; 
     } 

     private void SimpleListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      HasListBoxNewSelection = true; 
      HasListBoxNewSelection = false; 
     } 
    } 
} 
+0

aide ne marche pas toujours avec la question de filetage que j'ai peur, le problème est que la seule fonction par exemple de par exemple charger un document peut produire "stutter" dans l'interface, j'ai vraiment besoin de l'exécuter dans un thread séparé – Homde

+0

J'ai ajouté le code de toute façon ;-) Des choses comme le chargement d'un document que vous pouvez accomplir en utilisant BackgroundWorker. J'ai inclus un lien vers msdn dans la réponse ci-dessus. WPF n'autorisera jamais deux parties de la même interface utilisateur à s'exécuter sur des threads séparés. Vous devez effectuer votre tâche fastidieuse en arrière-plan, puis informer l'interface utilisateur par un événement que les nouvelles données sont prêtes. – Dabblernl

+0

Bien sûr que je le peux, je peux superposer des fenêtres les unes sur les autres, chacune en cours d'exécution de son propre fil et même être transparent. C'est un peu un hack mais ça marche. Je vois maintenant pourquoi un cadre ne pouvait pas fonctionner dans son propre fil – Homde