2015-11-22 2 views
0

J'essaie de comprendre comment utiliser au mieux la technique HandOffBehavior de WPF. En ce moment, j'ai une erreur de défilement dans mon application qui anime l'ouverture, fait défiler le message d'erreur, puis se ferme.WPF défilement chapiteau - HandOffBehavior

Je commençais juste à construire cette application WPF cette semaine. Le problème est que je n'arrive pas à me préparer gracieusement à un scénario comme lorsque l'utilisateur clique deux fois ou plus sur le bouton de connexion à intervalles réguliers. Je voudrais voir le chapiteau d'erreur seulement continuer à envoyer le texte d'erreur à travers l'écran lorsque l'utilisateur commet un tel comportement avec le bouton de connexion plutôt que d'ouvrir et de fermer les temps redondants multiples de sélection, etc. Voici le code approprié.

MainWindow.xaml.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Data.Entity; 
using System.Windows.Media.Animation; 
using PasswordHash; 

namespace ChatClient 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void logIn(object sender, RoutedEventArgs e) 
     { 
      string nameRecord = ""; 
      string passRecord = ""; 

      if (UsernameField.Text == "" || UserPassField.Password == "") 
      { 
       openErrorMarquee("Username and password required"); 
      } 
      else 
      { 
       using (otongadgethubEntities logCheck = new otongadgethubEntities()) 
       { 
        var userNullCheck = logCheck.users.FirstOrDefault(a => a.username == UsernameField.Text); 
        if (userNullCheck == null) 
        { 
         openErrorMarquee("Username does not exist"); 
        } 

        if (userNullCheck != null) 
        { 
         nameRecord = userNullCheck.username; 
        } 

        if (nameRecord == UsernameField.Text) 
        { 
         passRecord = Encrypt.MD5(UserPassField.Password).ToLower(); 
         if (passRecord == userNullCheck.password) 
         { 
          //Yay! User logged in! 
         } 
         else 
         { 
          openErrorMarquee("Password invalid"); 
         } 
        } 
       } 
      } 
     } 

     private void openErrorMarquee(string errorMessage) 
     { 
      errorMarquee.Visibility = System.Windows.Visibility.Visible; 

      DoubleAnimation openMarquee = new DoubleAnimation(); 
      openMarquee.From = 0; 
      openMarquee.To = 17; 
      openMarquee.Duration = new Duration(TimeSpan.FromSeconds(1.0)); 
      openMarquee.Completed += (s, doneEvent) => errorMarqueeScroll(errorMessage); 
      errorMarquee.BeginAnimation(Rectangle.HeightProperty, openMarquee, HandoffBehavior.Compose); 
     } 

     private void errorMarqueeScroll(string errorMessage) 
     { 
      errorText.Text = errorMessage; 
      errorText.Visibility = System.Windows.Visibility.Visible; 

      double height = errorCanvas.ActualHeight - errorText.ActualHeight; 
      errorText.Margin = new Thickness(0, height/2, 0, 0); 
      DoubleAnimation doubleErrorAnimation = new DoubleAnimation(); 
      doubleErrorAnimation.From = -errorText.ActualWidth; 
      doubleErrorAnimation.To = errorCanvas.ActualWidth; 

      //doubleErrorAnimation.RepeatBehavior = RepeatBehavior.Forever; 
      doubleErrorAnimation.Completed += new EventHandler(closeErrorMarquee); 
      doubleErrorAnimation.Duration = new Duration(TimeSpan.FromSeconds(7.0)); 
      errorText.BeginAnimation(Canvas.RightProperty, doubleErrorAnimation); 
     } 

     private void closeErrorMarquee(object sender, EventArgs e) 
     { 
      DoubleAnimation closeMarquee = new DoubleAnimation(); 
      closeMarquee.From = 17; 
      closeMarquee.To = 0; 
      closeMarquee.Duration = new Duration(TimeSpan.FromSeconds(1.0)); 
      closeMarquee.Completed += (s, doneEvent) => { 
       errorMarquee.Visibility = System.Windows.Visibility.Hidden; 
       errorText.Visibility = System.Windows.Visibility.Hidden; 
      }; 
      errorMarquee.BeginAnimation(Rectangle.HeightProperty, closeMarquee, HandoffBehavior.Compose); 
     } 
    } 
} 

Et voici le XAML pour ceux qui ont besoin de voir la fenêtre aussi:

<Window 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="ChatClient.MainWindow" 
     Title="MainWindow" Height="350" Width="525" Icon="media/favicon.gif" Background="#FF3C3636" Foreground="{x:Null}"> 
    <Window.Resources> 
     <Storyboard x:Key="logolayer2excompsoundfad_mp4"/> 
    </Window.Resources> 
    <Window.BorderBrush> 
     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
      <GradientStop Color="Black" Offset="0"/> 
      <GradientStop Color="#FF6F6D95" Offset="1"/> 
     </LinearGradientBrush> 
    </Window.BorderBrush> 
    <Window.Triggers> 
     <EventTrigger RoutedEvent="FrameworkElement.Loaded"> 
      <BeginStoryboard Storyboard="{StaticResource logolayer2excompsoundfad_mp4}"/> 
     </EventTrigger> 
    </Window.Triggers> 
    <Grid> 
     <Rectangle x:Name="Menu" Fill="#755E5E83" HorizontalAlignment="Left" Height="273" Margin="35,23,0,0" Stroke="Black" VerticalAlignment="Top" Width="446" RadiusY="27.5" RadiusX="27.5"/> 
     <Button Content="Log In" HorizontalAlignment="Left" Height="80" Margin="162,200,0,0" Style="{DynamicResource OTonButtonStyle1}" VerticalAlignment="Top" Width="187" FontFamily="Impact" FontSize="26.667" Foreground="#FF1C045B" Click="logIn"/> 
     <TextBox x:Name="UsernameField" HorizontalAlignment="Left" Height="25" Margin="204,57,0,0" TextWrapping="Wrap" Text="[Username]" VerticalAlignment="Top" Width="193" Background="#BD251E1E" UseLayoutRounding="False" FontFamily="Copperplate Gothic Light" FontSize="16"> 
      <TextBox.Foreground> 
       <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0"> 
        <GradientStop Color="#FF1E2E95" Offset="0.5"/> 
        <GradientStop Color="White" Offset="1"/> 
       </LinearGradientBrush> 
      </TextBox.Foreground> 
     </TextBox> 
     <TextBlock HorizontalAlignment="Left" Height="16" Margin="98,57,0,0" TextWrapping="Wrap" Text="Username:" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="16"> 
      <TextBlock.Foreground> 
       <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
        <GradientStop Color="#FF0A1D5F" Offset="0.374"/> 
        <GradientStop Color="#FF6E7FB9" Offset="1"/> 
       </LinearGradientBrush> 
      </TextBlock.Foreground> 
     </TextBlock> 
     <PasswordBox x:Name="UserPassField" HorizontalAlignment="Left" Height="25" Margin="204,99,0,0" VerticalAlignment="Top" Width="193" Background="#BD251E1E" UseLayoutRounding="False" FontFamily="Copperplate Gothic Light" FontSize="16"> 
      <PasswordBox.Foreground> 
       <LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0"> 
        <GradientStop Color="#FF1E2E95" Offset="0.5"/> 
        <GradientStop Color="White" Offset="1"/> 
       </LinearGradientBrush> 
      </PasswordBox.Foreground> 
     </PasswordBox> 
     <TextBlock HorizontalAlignment="Left" Height="16" Margin="98,99,0,0" TextWrapping="Wrap" Text="Password:" VerticalAlignment="Top" Width="101" FontFamily="Copperplate Gothic Light" FontSize="16"> 
      <TextBlock.Foreground> 
       <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
        <GradientStop Color="#FF0A1D5F" Offset="0.374"/> 
        <GradientStop Color="#FF6E7FB9" Offset="1"/> 
       </LinearGradientBrush> 
      </TextBlock.Foreground> 
     </TextBlock> 
     <Canvas ClipToBounds="True" Name="errorCanvas" Width="446" Height="17" Margin="36,152,35,151"> 
      <Rectangle x:Name="errorMarquee" Fill="#FF0A0A0C" HorizontalAlignment="Left" Height="17" Stroke="#FF5B1D1D" VerticalAlignment="Top" Width="446" Canvas.Left="-1" Visibility="Hidden"/> 
      <TextBlock x:Name="errorText" HorizontalAlignment="Left" Height="16" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="690" FontFamily="Copperplate Gothic Bold" FontSize="16" Foreground="#FF7E0202" Visibility="Hidden"/> 
     </Canvas> 
    </Grid> 
</Window> 

Quelqu'un a des suggestions, peut-être?

Répondre

0

vous pouvez simplement utiliser un drapeau pour vérifier

private static flag = true; 
private void logIn(object sender, RoutedEventArgs e) 
    { 
     if(flag){ 
     flag=false; 
     string nameRecord = ""; 
     string passRecord = ""; 

     if (UsernameField.Text == "" || UserPassField.Password == "") 
     { 
      openErrorMarquee("Username and password required"); 
     } 
     else 
     { 
      using (otongadgethubEntities logCheck = new otongadgethubEntities()) 
      { 
       var userNullCheck = logCheck.users.FirstOrDefault(a => a.username == UsernameField.Text); 
       if (userNullCheck == null) 
       { 
        openErrorMarquee("Username does not exist"); 
       } 

       if (userNullCheck != null) 
       { 
        nameRecord = userNullCheck.username; 
       } 

       if (nameRecord == UsernameField.Text) 
       { 
        passRecord = Encrypt.MD5(UserPassField.Password).ToLower(); 
        if (passRecord == userNullCheck.password) 
        { 
         //Yay! User logged in! 
        } 
        else 
        { 
         openErrorMarquee("Password invalid"); 
        } 
       } 
      } 
     } 
     } 
     else 
     { 
     openErrorMarquee("you pressed more one time"); 
     } 
    } 
+0

Merci de répondre. Je dois dire cependant, en raison de la structure des événements (en particulier depuis quand on appelle quand une autre animation est terminée, en ouvrant le rectangle de sélection, en le fermant, etc.) que cela ne résout pas suffisamment le problème. Il ne fait que déclencher à nouveau tous les événements, puis le même problème persistera - la fermeture du chapiteau plus tôt que prévu, l'ouverture d'une autre heure même si je ne veux que «ouvrir» une fois pour faire défiler les messages d'erreur, etc. essayer de réparer les pauses dans cette interface utilisateur. –

+0

Comme si j'appuyais sur le bouton Connexion trois fois super rapide, tout le comportement de l'animation errorMarquee et son errorText deviendraient haywire, avec finalement le errorText se cachant pendant un moment, l'ouverture et l'ouverture du rectangle de sélection, etc. –

0

Vous pouvez utiliser StopWatch pour vérifier les clics rapides. Dans l'exemple de code donné ci-dessous, essayez d'appuyer sur le bouton lent et rapide.

Stopwatch w = new Stopwatch(); 
    long milliseconds_prev = 0; 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     if (_checkFastClicks()) 
     { 
      Debug.WriteLine("Fast click"); 
     } 
     else 
      Debug.WriteLine("Slow click"); 
    } 

    bool _checkFastClicks() 
    { 
     bool result = false; 

     if (!w.IsRunning) 
     { 
      w.Start(); 
     } 
     if (w.IsRunning) 
     { 
      if (w.ElapsedMilliseconds - milliseconds_prev < 500)//imp 
      { 
       if (w.ElapsedMilliseconds > 0) 
       { 
        milliseconds_prev = w.ElapsedMilliseconds; 
        result = true; 
       } 
       else 
        result = false; 
      } 
      else 
      { 
       milliseconds_prev = 0; 
       w.Reset(); 
       w.Stop(); 
       result = false; 
      } 
     } 

     return result; 
    } 
+0

Idée intéressante. Je vais devoir essayer ça plus tard, peut-être quand nous serons à l'aéroport de Denver. Merci! Je vous ferai savoir si je trouve quelque chose –