Introduzione

In questo nuovo articolo continuiamo a esplorare librerie che servono per arricchire le proprie applicazioni in WPF. Ora vedremo la libreria WPF Login per avere un nuovo modo di fare il login e di gestire gli utenti.

Anche questa libreria non è recente ma vale la pena provarla e usare nelle proprie applicazioni. Tra l’altro con un minimo sforzo in più potete aggiungere valore alle vostre stesse applicazioni.

Implementazione

Vediamo come implementare l'esempio proposto nei nostri progetti WPF.

Questo è il link per scaricarla: http://wpflogin.codeplex.com/

Esistono anche su Github delle librerie per il login, ma per ora proviamo questa.

Una volta scaricato e scompattato il file scaricato, andiamo ad aprire il progetto su Visual Studio per analizzarlo. Vedrete che si tratta di un unico progetto in WPF, per cui non c’è da aggiungere alcuna Reference nel proprio progetto. Si prende il codice XAML e quello behind e lo si incolla.

Vediamo come funziona. Lanciando l’applicazione, vedremo una schermata come questa:

Non è carina la finestra?

Mettiamo user come nome utente e password come password. Poi vedremo dove sono memorizzati questi dati per poterli cambiare e recuperarli ad esempio da un database.

Se i dati inseriti sono corretti avremo quindi la “schermata principale” del programma. In questo caso altro non è che una pagina con la scritta “Main Window” ma è chiaro che poi ci sarà mostrata la schermata principale della nostra applicazione WPF.

Vediamo quindi qual è la parte di codice da esportare e da inserire nelle nostre applicazioni.

Apriamo Visual Studio e creiamo un nuovo progetto WPF chiamandolo “GestionaleAzienda”

Nella Main Window ci metteremo qualcosa per far finta che questo sia il nostro software appena sviluppato, quindi a vostro piacere ci mettete qualche TextBlock, qualche TextBox e un pulsando, facendo finta che sia una schermata per la visualizzazione/modifica di dati.

Creiamo ora una nuova finestra che chiameremo Login.

Prima cosa da fare ora, per non dimenticarci in seguito, è indicare che l’applicazione deve essere aperta con questa finestra e non con la MainWindow. Per fare questo, bisogna andare nel file App.xaml e andare a moficare lo StartupUri in questo modo:

StartupUri="Login.xaml"

Già che siamo su questo file aggiungiamoci all’interno del tag Resources il seguente codice:

<ResourceDictionary
 <ResourceDictionary.MergedDictionaries
 <ResourceDictionary Source="Style.xaml"/> 
 </ResourceDictionary.MergedDictionaries
 </ResourceDictionary

Andiamo ora ad aggiungere al progetto un nuovo file dizionario di risorse chiamato Style.xaml.

Andiamo quindi ora a mettere il seguente codice sul file appena creato:

 

<!-- Style for the User Name textbox --> 
   <Style x:Key="txtUserStyle" TargetType="{x:Type TextBox}" BasedOn="{x:Null}"
   <Setter Property="Foreground" Value="Black"/> 
   <Setter Property="HorizontalAlignment" Value="Center"/> 
   <Setter Property="VerticalContentAlignment" Value="Center"/> 
   <Setter Property="Width" Value="225"/> 
   <Setter Property="Height" Value="25"/> 
   <Setter Property="FontSize" Value="12"/> 
   <Setter Property="Padding" Value="1"/> 
   <Setter Property="Margin" Value="5"/> 
   <Setter Property="AllowDrop" Value="true"/> 
   <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
   <Setter Property="Template"
   <Setter.Value
   <ControlTemplate TargetType="{x:Type TextBox}"
   <Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4"
   <Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3"
   <Grid
   <Label x:Name="lblUsr" Content="User" FontSize="12" VerticalAlignment="Center" Margin="2,0,0,0" FontFamily="Fonts/#Cooper Std" Foreground="#828385" Padding="0" HorizontalAlignment="Left"/> 
   <ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/> 
   </Grid
   </Border
   </Border
   <ControlTemplate.Triggers
   <Trigger Property="ClipToBounds" Value="True"
   <Setter Property="Visibility" TargetName="lblUsr" Value="Hidden"/> 
   </Trigger
   </ControlTemplate.Triggers
   </ControlTemplate
   </Setter.Value
   </Setter
   </Style
   <!-- Style for the Password textbox --> 
   <Style x:Key="txtPasswordStyle" TargetType="{x:Type PasswordBox}" BasedOn="{x:Null}"
   <Setter Property="Foreground" Value="Black"/> 
   <Setter Property="HorizontalAlignment" Value="Center"/> 
   <Setter Property="VerticalContentAlignment" Value="Center"/> 
   <Setter Property="Width" Value="225"/> 
   <Setter Property="Height" Value="25"/> 
   <Setter Property="FontSize" Value="12"/> 
   <Setter Property="Padding" Value="1"/> 
   <Setter Property="Margin" Value="5"/> 
   <Setter Property="AllowDrop" Value="true"/> 
   <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
   <Setter Property="Template"
   <Setter.Value
   <ControlTemplate TargetType="{x:Type PasswordBox}"
   <Border x:Name="OuterBorder" BorderBrush="#5AFFFFFF" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4"
   <Border x:Name="InnerBorder" Background="#FFFFFFFF" BorderBrush="#33000000" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3"
   <Grid
   <Label x:Name="lblPwd" Content="Password" FontSize="12" VerticalAlignment="Center" Margin="2,0,0,0" FontFamily="Fonts/#Cooper Std" Foreground="#828385" Padding="0"/> 
   <ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ContentHost"/> 
   </Grid
   </Border
   </Border
   <ControlTemplate.Triggers
   <Trigger Property="ClipToBounds" Value="True"
   <Setter Property="Visibility" TargetName="lblPwd" Value="Hidden"/> 
   </Trigger
   </ControlTemplate.Triggers
   </ControlTemplate
   </Setter.Value
   </Setter
   </Style
   <!-- Button Style --> 
   <Style x:Key="Button" TargetType="{x:Type Button}"
   <Setter Property="OverridesDefaultStyle" Value="True"/> 
   <Setter Property="Margin" Value="2"/> 
   <Setter Property="FontFamily" Value="Fonts/#Cooper Std"/> 
   <Setter Property="FontSize" Value="12px"/> 
   <Setter Property="Foreground" Value="#FFFFFFFF"/> 
   <Setter Property="Background" Value="#FF154693"/> 
   <Setter Property="Template"
   <Setter.Value
   <ControlTemplate TargetType="{x:Type Button}"
   <Border x:Name="Border" BorderThickness="2" Padding="4,2" BorderBrush="DarkGray" CornerRadius="3" Background="{TemplateBinding Background}"
   <Grid
   <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="Content"/> 
   </Grid
   </Border
   <ControlTemplate.Triggers
   <Trigger Property="IsMouseOver" Value="True"
   <Setter TargetName="Border" Property="BorderBrush" Value="#FF286CAF" /> 
   <Setter Property="Foreground" Value="#FF4788c8" /> 
   </Trigger
   <Trigger Property="IsPressed" Value="True"
   Setter Property="Background" Value="#FF112F60" /> 
   <Setter TargetName="Content" Property="RenderTransform"
   <Setter.Value
   <TranslateTransform Y="1.0" /> 
   </Setter.Value
   </Setter
   </Trigger
   </ControlTemplate.Triggers
   </ControlTemplate
   </Setter.Value
   </Setter
   </Style
   <!-- Button Style End --> 

 

 

Ora mettiamo nella pagina XAML di Login.wpf il seguente codice:

Height="274.3" Width="549.092" 
Background="{x:Null}" 
WindowStartupLocation="CenterScreen" 
ResizeMode="NoResize" 
WindowStyle="None" 
ShowInTaskbar="False" 
AllowsTransparency="True" 
MouseDown="Window_MouseDown" 
Loaded="Window_Loaded"> 

All’interno del tag Window mentre il seguente codice al posto del tag Grid.

<Window.Resources
 <Storyboard x:Key="LoadingAnimation" RepeatBehavior="Forever" SpeedRatio="3"
 <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="epHover2" Storyboard.TargetProperty="(UIElement.Visibility)"
 <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Visible}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:02" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:04" Value="{x:Static Visibility.Hidden}"/> 
 </ObjectAnimationUsingKeyFrames
 <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="epHover4" Storyboard.TargetProperty="(UIElement.Visibility)"
 <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:02" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:03" Value="{x:Static Visibility.Visible}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:04" Value="{x:Static Visibility.Hidden}"/> 
 </ObjectAnimationUsingKeyFrames
 <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="epHover3" Storyboard.TargetProperty="(UIElement.Visibility)"
 <DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:02" Value="{x:Static Visibility.Visible}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:03" Value="{x:Static Visibility.Hidden}"/> 
 </ObjectAnimationUsingKeyFrames
 <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="epHover1" Storyboard.TargetProperty="(UIElement.Visibility)"
 <DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Hidden}"/> 
 <DiscreteObjectKeyFrame KeyTime="00:00:04" Value="{x:Static Visibility.Visible}"/> 
 </ObjectAnimationUsingKeyFrames
 </Storyboard
 </Window.Resources
 <Window.Effect
 <DropShadowEffect BlurRadius="25" Opacity="0.405" ShadowDepth="20" RenderingBias="Performance"/> 
 </Window.Effect
 <Grid
 <Grid.ColumnDefinitions
 <ColumnDefinition Width="0.772*" /> 
 <ColumnDefinition Width="0.228*" /> 
 </Grid.ColumnDefinitions
 <Grid.RowDefinitions
 <RowDefinition Height="0.393*" /> 
 <RowDefinition Height="0.607*" /> 
 </Grid.RowDefinitions
 <Canvas x:Name="Background" Margin="0,0,30.092,31.3" Grid.ColumnSpan="2" Grid.RowSpan="2"
 <Path Data="F1 M 534.000,245.000 C 534.000,251.627 528.627,257.000 522.000,257.000 L 27.001,257.000 C 20.373,257.000 15.001,251.627 15.001,245.000 L 15.001,27.000 C 15.001,20.373 20.373,15.000 27.001,15.000 L 522.000,15.000 C 528.627,15.000 534.000,20.373 534.000,27.000 L 534.000,245.000 Z" Stretch="Fill" Width="519" Height="243"
 <Path.Fill
 <LinearGradientBrush MappingMode="Absolute" StartPoint="-208.332,952.442" EndPoint="118.961,562.390"
 <LinearGradientBrush.Transform
 <MatrixTransform Matrix="1.000,0.000,-0.000,-1.000,319.186,893.416" /> 
 </LinearGradientBrush.Transform
 <GradientStop Offset="0.000" Color="#ff00698d"/> 
 <GradientStop Offset="1.000" Color="#ff1b75bb"/> 
 </LinearGradientBrush
 </Path.Fill
 </Path
 <Path Data="F1 M 534.000,245.000 L 534.000,27.000 C 534.000,20.373 528.627,15.000 522.000,15.000 L 495.790,15.000 C 518.093,85.111 555.962,200.770 437.124,221.195 C 323.772,240.678 130.870,206.203 15.000,181.094 L 15.000,245.000 C 15.000,251.627 20.372,257.000 27.000,257.000 L 522.000,257.000 C 528.627,257.000 534.000,251.627 534.000,245.000 Z" Stretch="Fill" Width="519" Height="243"
 <Path.Fill
 <LinearGradientBrush MappingMode="Absolute" StartPoint="-129.701,858.732" EndPoint="118.961,562.389"
 <LinearGradientBrush.Transform
 <MatrixTransform Matrix="1.000,0.000,-0.000,-1.000,319.186,893.416" /> 
 </LinearGradientBrush.Transform
 <GradientStop Offset="0.012" Color="#ff1b75bb"/> 
 <GradientStop Offset="1.000" Color="#ff213f99"/> 
 </LinearGradientBrush
 </Path.Fill
 </Path
 </Canvas
 <TextBlock x:Name="txtAppName" Margin="26,27.416,5.313,23.888" FontStyle="Italic" FontWeight="Bold" FontSize="36" FontFamily="Fonts/#Cooper Std" Text="Gestionale Azienda" Foreground="#FFA3A4A9"
 <TextBlock.Effect
 <DropShadowEffect/> 
 </TextBlock.Effect
 </TextBlock
 <TextBlock x:Name="txtMsg" Margin="26,0,5.313,38.851" FontSize="16" FontWeight="Bold" VerticalAlignment="Bottom" Height="21" FontStyle="Normal" FontFamily="Segoe UI" Grid.Row="1" Foreground="#FFFF0000" Visibility="Hidden"/> 
 <Canvas x:Name="grdMainControls" Margin="164.174,-10.594,34.725,0" VerticalAlignment="Top" Height="85.551" Grid.Row="1"
 <TextBox x:Name="txtUser" Style="{StaticResource txtUserStyle}" Margin="0" TextWrapping="Wrap" Height="25 " Text="" HorizontalAlignment="Stretch" GotFocus="txtUser_GotFocus" LostFocus="txtUser_LostFocus" TextChanged="txtUser_TextChanged" FontFamily="Fonts/#Cooper Std" PreviewKeyDown="txtUser_PreviewKeyDown"/> 
 <PasswordBox x:Name="txtPassword" Style="{StaticResource txtPasswordStyle}" Margin="0" HorizontalAlignment="Stretch" LostFocus="txtPassword_LostFocus" GotFocus="txtPassword_GotFocus" Password="" PasswordChanged="txtPassword_PasswordChanged" FontFamily="Fonts/#Cooper Std" Canvas.Top="31.551" PreviewKeyDown="txtPassword_PreviewKeyDown"/> 
 <Button x:Name="btnLogin" Click="btnLogin_Click" Style="{StaticResource Button}" Margin="0" Content="Login" FontWeight="Bold" FontFamily="Fonts/#Cooper Std" FontSize="14" FontStyle="Normal" Width="110" Height="25" Canvas.Top="60.551"/> 
 <Button x:Name="btnCancel" Click="btnCancel_Click" Style="{StaticResource Button}" Width="110" Margin="0" Content="Cancel" FontWeight="Bold" FontSize="14" FontFamily="Fonts/#Cooper Std" Height="25" Canvas.Left="115" Canvas.Top="60.551"/> 
 </Canvas
 <TextBlock x:Name="txtVersion" Margin="0,8,-56.768,0" FontStyle="Normal" FontWeight="Bold" FontSize="16" VerticalAlignment="Top" Height="21" TextAlignment="Right" Text="Version" Width="229.623" HorizontalAlignment="Right" FontFamily="Fonts/#Cooper Std" Foreground="#FF3F3F3F"/> 
 <Grid x:Name="grdLoading" Margin="195.997,6.5,100.175,0" Grid.Row="1" Opacity="0.995" VerticalAlignment="Top" Height="44.832" Visibility="Hidden"
 <Canvas x:Name="CirclesBehind" Margin="8,8,11.764,11.423"
 <Ellipse Stroke="{x:Null}" x:Name="ep1" Width="25.409" Fill="#FF08547E" Height="25.409"/> 
 <Ellipse Stroke="{x:Null}" x:Name="ep2" Width="25.408" Fill="#FF08547E" Height="25.409" Canvas.Left="27.614"/> 
 <Ellipse Stroke="{x:Null}" x:Name="ep3" Fill="#FF08547E" Width="25.121" Height="25.409" Canvas.Left="55.228"/> 
 <Ellipse Stroke="{x:Null}" x:Name="ep4" Width="25.409" Fill="#FF08547E" Height="25.409" Canvas.Left="82.554"/> 
 </Canvas
 <Canvas x:Name="CirclesAbove" Margin="8,8,11.764,11.423"
 <Ellipse Stroke="{x:Null}" x:Name="epHover1" Width="25.409" Opacity="1" Fill="#FF3CB2CD" Height="25.409"/> 
 <Ellipse Stroke="{x:Null}" x:Name="epHover2" Width="25.408" Opacity="1" Fill="#FF3CB2CD" Height="25.409" Canvas.Left="27.614"/> 
 <Ellipse Stroke="{x:Null}" x:Name="epHover3" Opacity="1" Fill="#FF3CB2CD" Width="25.121" Height="25.409" Canvas.Left="55.228"/> 
 <Ellipse Stroke="{x:Null}" x:Name="epHover4" Width="25.409" Opacity="1" Fill="#FF3CB2CD" Height="25.409" Canvas.Left="82.554"/> 
 </Canvas
 </Grid
 </Grid>

Passiamo ora al code-behind di Login.xaml.

Sostituiamo tutto quello che c’è all’interno di Login : Window con:

#region | Declarations |
 private BackgroundWorker loadingTimer;
 #region | Move Window |
 public const int WM_NCLBUTTONDOWN = 0xA1;
 public const int HT_CAPTION = 0x2;
 [DllImportAttribute("user32.dll")]
 public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
 [DllImportAttribute("user32.dll")]
 public static extern bool ReleaseCapture();
 #endregion
 #endregion
 /// <summary>
 /// Initializes a new instance of the <see cref="winLogin"/> class.
 /// </summary>
 public Login()
 {
 InitializeComponent();
 }
 #region |- Events -|
 /// <summary>
 /// Handles the Loaded event of the Window control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void Window_Loaded(object sender, RoutedEventArgs e)
 {
 this.txtVersion.Text = "v. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
 }
 /// <summary>
 /// Handles the Click event of the btnAceptar control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void btnLogin_Click(object sender, RoutedEventArgs e)
 {
 // Validation
 this.ShowMessage(Visibility.Hidden, "");
 if (string.IsNullOrEmpty(this.txtUser.Text.Trim()))
 {
 this.ShowMessage(Visibility.Visible, "Username is requiered.");
 this.txtUser.Focus();
 return;
 }
 if (string.IsNullOrEmpty(this.txtPassword.Password.Trim()))
 {
 this.ShowMessage(Visibility.Visible, "Password is requiered.");
 this.txtPassword.Focus();
 return;
 }
 try
 {
 // Hide the textbox, show and begin the animation
 this.grdMainControls.Visibility = Visibility.Hidden;
 this.grdLoading.Visibility = Visibility.Visible;
 Storyboard strLoading = (Storyboard)this.FindResource("LoadingAnimation");
 strLoading.Begin();
 // Thread
 this.loadingTimer = new BackgroundWorker();
 this.loadingTimer.WorkerReportsProgress = true;
 this.loadingTimer.WorkerSupportsCancellation = true;
 // Events
 this.loadingTimer.DoWork += new DoWorkEventHandler(loadingTimer_DoWork);
 this.loadingTimer.RunWorkerCompleted += new RunWorkerCompletedEventHandler(loadingTimer_RunWorkerCompleted);
 // Parameters
 Dictionary<string, string> Parm = new Dictionary<string, string>();
 Parm.Add("User", this.txtUser.Text);
 Parm.Add("Password", this.txtPassword.Password);
 this.loadingTimer.RunWorkerAsync(Parm);
 }
 catch (Exception)
 {
 this.grdMainControls.Visibility = Visibility.Visible;
 this.grdLoading.Visibility = Visibility.Hidden;
 this.ShowMessage(Visibility.Visible, "An Error as ocurred.");
 }
 }
 #region |- Thread Events -|
 /// <summary>
 /// Handles the DoWork event of the loadingTimer control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
 private void loadingTimer_DoWork(object sender, DoWorkEventArgs e)
 {
 Dictionary<string, string> P = (Dictionary<string, string>)e.Argument;
 // Temporary sleep so you can see the animation.
 System.Threading.Thread.Sleep(5000);
 // Validar las credenciales
 if (this.ValidateCredentials(P["User"].ToString(), P["Password"].ToString()))
 e.Result = true;
 else
 e.Result = false;
 }
 /// <summary>
 /// Handles the RunWorkerCompleted event of the loadingTimer control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
 private void loadingTimer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 {
 try
 {
 // Stop the animation
 Storyboard strLoading = (Storyboard)FindResource("LoadingAnimation");
 strLoading.Stop();
 if ((bool)e.Result) // Success
 {
 this.ShowMessage(Visibility.Visible, "Login Successfully");
 MainWindow win = new MainWindow();
 win.Show();
 this.Close();
 }
 else
 {
 this.grdLoading.Visibility = Visibility.Hidden;
 this.grdMainControls.Visibility = Visibility.Visible;
 }
 }
 catch (Exception)
 {
 }
 }
 #endregion
 /// <summary>
 /// Handles the Click event of the btnCancelar control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void btnCancel_Click(object sender, RoutedEventArgs e)
 {
 this.Close();
 }
 /// <summary>
 /// Handles the GotFocus event of the IdUsuario control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void txtUser_GotFocus(object sender, RoutedEventArgs e)
 {
 // Hide the label lblUsr
 txtUser.ClipToBounds = true;
 }
 /// <summary>
 /// Handles the LostFocus event of the IdUsuario control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void txtUser_LostFocus(object sender, RoutedEventArgs e)
 {
 // Show the label lblUsr
 if (string.IsNullOrEmpty(txtUser.Text))
 {
 txtUser.ClipToBounds = false;
 }
 }
 /// <summary>
 /// Handles the GotFocus event of the Password control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void txtPassword_GotFocus(object sender, RoutedEventArgs e)
 {
 // Hide the label lblPwd
 txtPassword.ClipToBounds = true;
 }
 /// <summary>
 /// Handles the LostFocus event of the Password control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void txtPassword_LostFocus(object sender, RoutedEventArgs e)
 {
 // Show the label lblPwd
 if (string.IsNullOrEmpty(txtPassword.Password))
 {
 txtPassword.ClipToBounds = false;
 }
 }
 /// <summary>
 /// Handles the TextChanged event of the IdUsuario control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.Controls.TextChangedEventArgs"/> instance containing the event data.</param>
 private void txtUser_TextChanged(object sender, TextChangedEventArgs e)
 {
 ShowMessage(Visibility.Hidden, "");
 }
 /// <summary>
 /// Handles the PasswordChanged event of the Password control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
 private void txtPassword_PasswordChanged(object sender, RoutedEventArgs e)
 {
 ShowMessage(Visibility.Hidden, "");
 }
 /// <summary>
 /// Handles the MouseDown event of the Window control.
 /// Moves the form.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
 private void Window_MouseDown(object sender, MouseButtonEventArgs e)
 {
 if (e.LeftButton == MouseButtonState.Pressed)
 {
 ReleaseCapture();
 // Move the window.
 SendMessage((new WindowInteropHelper(this)).Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
 }
 }
 /// <summary>
 /// Handles the PreviewKeyDown event of the txtUser control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
 private void txtUser_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
 {
 if (e.Key == Key.Enter)
 {
 this.btnLogin.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
 this.txtUser.Focus();
 e.Handled = true;
 }
 }
 /// <summary>
 /// Handles the PreviewKeyDown event of the txtPassword control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
 private void txtPassword_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
 {
 if (e.Key == Key.Enter)
 {
 this.btnLogin.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
 this.txtPassword.Focus();
 e.Handled = true;
 }
 }
 #endregion
 #region Functions
 /// <summary>
 /// Shows the message.
 /// </summary>
 /// <param name="Show">if set to <c>true</c> [show].</param>
 /// <param name="Message">The message.</param>
 private void ShowMessage(Visibility Show, string Message)
 {
 this.txtMsg.Text = Message;
 this.txtMsg.Visibility = Show;
 }
 /// <summary>
 /// Validates the credentials against SQL Server.
 /// </summary>
 /// <returns>True if the credentials are valid</returns>
 private bool ValidateCredentials(string strUser, string strPassword)
 {
 #region |- SQL Server -|
 //try
 //{
 //  ServerConnection myServerConn = new ServerConnection();
 //  myServerConn.LoginSecure = true;
 //  myServerConn.ConnectAsUser = true;
 //  // I asume that your current machine is the name of the server.
 //  myServerConn.ServerInstance = Environment.MachineName.ToString();
 //  myServerConn.ConnectAsUserName = txtUser.Text.Trim();
 //  myServerConn.ConnectAsUserPassword = txtPassword.Password.Trim();
 //  myServerConn.Connect();
 //  return true;
 //}
 //catch (Exception ex)
 //{
 //  ShowMessage(Visibility.Visible, "Logon failure: unknown user name or bad password.");
 //  Console.WriteLine(ex.Message);
 //  return false;
 //}
 #endregion
 #region |- Static Login -|
 if (strUser.Trim() == "user" && strPassword.Trim() == "password")
 return true;
 else
 {
 Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (System.Threading.SendOrPostCallback)delegate
 {
 ShowMessage(Visibility.Visible, "Logon failure: unknown user name or bad password.");
 }, null);
 return false;
 }
 #endregion
 }
 #endregion

Vedete che nella parte commentata c’è la parte di verifica delle credenziali nel caso di un database SQL Server, altrimenti subito più giù si può impostare la username e password.

Abbiamo quasi finito.

Prima di compilare il progetto, dobbiamo andare ad aggiungere le using mancanti.

using System.ComponentModel;

using System.Runtime.InteropServices;

using System.Windows.Interop;

using System.Windows.Media.Animation;

Lanciamo l’applicazione ed ecco che apparirà la finestra come quella originale.

Conclusioni

Ovviamente possiamo cambiare colori e stile, sbizzarrendoci come vogliamo, l’unico limite è la fantasia.