WPF: depuración

Es un mecanismo sistemático para identificar y corregir los errores o defectos en un fragmento de código que no se comportan de la misma forma que esperabas. La depuración de una aplicación compleja donde los subsistemas están estrechamente acoplados no es tan fácil, porque corregir errores en un subsistema puede crear errores en otro subsistema.

Depurar en C #

En las aplicaciones WPF, los programadores se ocupan de dos lenguajes, como C # y XAML. Si está familiarizado con la depuración en cualquier lenguaje procedimental como C # o C / C ++ y también conoce el uso de puntos de interrupción, puede depurar la parte C # de su aplicación fácilmente.

Tomemos un ejemplo simple para demostrar cómo depurar un código C #. Cree un nuevo proyecto de WPF con el nombreWPFDebuggingDemo. Arrastre cuatro etiquetas, tres cuadros de texto y un botón de la caja de herramientas. Eche un vistazo al siguiente código XAML.

<Window x:Class = "WPFDebuggingDemo.Window1" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "Window1" Height = "400" Width = "604"> 
	
   <Grid> 
      <TextBox Height = "23" Margin = "0,44,169,0" Name = "textBox1"  
         VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120" /> 
			
      <TextBox Height = "23" Margin = "0,99,169,0" Name = "textBox2"  
         VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120" /> 
			
      <TextBox HorizontalAlignment = "Right" Margin = "0,153,169,0"  
         Name = "textBox3" Width = "120" Height = "23" VerticalAlignment = "Top" /> 
			
      <Label Height = "28" Margin = "117,42,0,0" Name = "label1"  
         VerticalAlignment = "Top" HorizontalAlignment = "Left" Width = "120">
         Item 1</Label> 
			
      <Label Height = "28" HorizontalAlignment = "Left"  
         Margin = "117,99,0,0" Name = "label2" VerticalAlignment = "Top" Width = "120">
         Item 2</Label> 
			
      <Label HorizontalAlignment = "Left" Margin = "117,153,0,181"  
         Name = "label3" Width = "120">Item 3</Label>
			
      <Button Height = "23" HorizontalAlignment = "Right" Margin = "0,0,214,127"
         Name = "button1" VerticalAlignment = "Bottom" Width = "75"  
         Click = "button1_Click">Total</Button> 
			
      <Label Height = "28" HorizontalAlignment = "Right"  
         Margin = "0,0,169,66" Name = "label4" VerticalAlignment = "Bottom" Width = "120"/> 
			
   </Grid> 
	
</Window>

A continuación se muestra el código C # en el que se implementa un evento de clic de botón.

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;  

namespace WPFDebuggingDemo { 
   /// <summary> 
      /// Interaction logic for Window1.xaml 
   /// </summary> 
	
   public partial class Window1 : Window { 
	
      public Window1() {
         InitializeComponent();
      }
		
      private void button1_Click(object sender, RoutedEventArgs e) {
		
         if (textBox1.Text.Length > 0 && textBox2.Text.Length > 0 && textBox2.Text.Length > 0) {
            double total = Convert.ToDouble(textBox1.Text) + 
            Convert.ToDouble(textBox2.Text) + Convert.ToDouble(textBox3.Text); 
            label4.Content = total.ToString(); 
         } 
         else { 
            MessageBox.Show("Enter the value in all field.");
         } 
      } 
   } 
}

Cuando compile y ejecute el código anterior, producirá la siguiente ventana. Ahora ingrese valores en los cuadros de texto y presione el botón Total. Obtendrá el valor total después de la suma de todos los valores ingresados ​​en los cuadros de texto.

Si intenta ingresar valores que no sean valores reales, la aplicación anterior se bloqueará. Para encontrar y resolver el problema (por qué se bloquea), puede insertar puntos de interrupción en el evento de clic del botón.

Escribamos "abc" en el elemento 1 como se muestra a continuación.

Al hacer clic en el botón Total, verá que el programa se detiene en el punto de interrupción.

Ahora mueva el cursor hacia el cuadro de texto1.Texto y verá que el programa está intentando agregar abc valor con los otros valores, por lo que el programa se bloquea.

Depurar en XAML

Si espera el mismo tipo de depuración en XAML, se sorprenderá al saber que todavía no es posible depurar el código XAML como depurar cualquier otro código de lenguaje de procedimiento. Cuando escuche el término depuración en código XAML, significa tratar de encontrar un error.

  • En el enlace de datos, sus datos no se muestran en la pantalla y no sabe por qué

  • O un problema está relacionado con diseños complejos.

  • O un problema de alineación o problemas en el color de los márgenes, superposiciones, etc. con algunas plantillas extensas como ListBox y combo box.

La depuración de un programa XAML es algo que normalmente se hace para comprobar si los enlaces funcionan; y si no funciona, verifique qué está mal. Lamentablemente, no es posible establecer puntos de interrupción en los enlaces XAML, excepto en Silverlight, pero podemos usar la ventana Salida para comprobar si hay errores de enlace de datos. Echemos un vistazo al siguiente código XAML para encontrar el error en el enlace de datos.

<Window x:Class = "DataBindingOneWay.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <StackPanel Name = "Display"> 
         <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0"> 
            <TextBlock Text = "Name: " Margin = "10" Width = "100"/> 
            <TextBlock Margin = "10" Width = "100" Text = "{Binding FirstName}"/> 
         </StackPanel> 
			
         <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0"> 
            <TextBlock Text = "Title: " Margin = "10" Width = "100"/> 
            <TextBlock Margin = "10" Width = "100" Text = "{Binding Title}" /> 
         </StackPanel> 
			
      </StackPanel> 
   </Grid> 
	
</Window>

Las propiedades de texto de dos bloques de texto se establecen en "Nombre" y "Título" de forma estática, mientras que otros dos bloques de texto Las propiedades de texto están vinculadas a "Nombre" y "Título" pero las variables de clase son Nombre y Título en la clase Empleado que se muestra a continuación.

Hemos escrito intencionalmente un nombre de variable incorrecto para entender dónde podemos encontrar este tipo de error cuando no se muestra el resultado deseado.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;  

namespace DataBindingOneWay { 

   public class Employee { 
      public string Name { get; set; } 
      public string Title { get; set; }  
		
      public static Employee GetEmployee() { 
		
         var emp = new Employee() { 
            Name = "Ali Ahmed", Title = "Developer" 
         }; 
			
         return emp; 
      }  
   } 
}

Aquí está la implementación de la clase MainWindow en código C #.

using System; 
using System.Windows; 
using System.Windows.Controls; 
 
namespace DataBindingOneWay { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml
   /// </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         DataContext = Employee.GetEmployee(); 
      } 
   } 
}

Ejecutemos esta aplicación y podrá ver inmediatamente en nuestra ventana principal que nos hemos vinculado correctamente al título de ese objeto Empleado, pero el nombre no está vinculado.

Para comprobar qué pasó con el nombre, veamos la ventana de salida donde se genera una gran cantidad de registro.

Lo fácil de encontrar un error es simplemente buscar el error y encontrará el siguiente error que dice "Error de ruta de BindingExpression: la propiedad 'FirstName' no se encuentra en el 'objeto' ''

System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName'
   property not found on 'object' ''Employee' (HashCode=11611730)'.
   BindingExpression:Path = FirstName; DataItem = 'Employee' (HashCode = 11611730);
   target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Lo que indica claramente que FirstName no es miembro de la clase Empleado, por lo que ayuda a solucionar este tipo de problemas en su aplicación.

Cuando cambie el Nombre a Nombre nuevamente, verá el resultado deseado.

Herramientas de depuración de IU para XAML

Se introdujeron herramientas de depuración de IU para XAML con Visual Studio 2015 para inspeccionar el código XAML en tiempo de ejecución. Con la ayuda de estas herramientas, el código XAML se presenta en forma de un árbol visual de su aplicación WPF en ejecución y también las diferentes propiedades de los elementos de la interfaz de usuario en el árbol. Para habilitar estas herramientas, siga los pasos que se indican a continuación.

  • Vaya al menú Herramientas y seleccione Opciones en el menú Herramientas.
  • Se abrirá el siguiente cuadro de diálogo.
  • Vaya a Opciones generales en el elemento Depuración en el lado izquierdo.
  • Marque la opción resaltada, es decir, "Habilitar herramientas de depuración de interfaz de usuario para XAML" y haga clic en el botón Aceptar.

Ahora ejecute cualquier aplicación XAML o use el siguiente código XAML.

<Window x:Class = "XAMLTestBinding.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <ComboBox Name = "comboBox"  Margin = "50" Width = "100"> 
         <ComboBoxItem Content = "Green" /> 
         <ComboBoxItem  Content = "Yellow" IsSelected = "True" />
         <ComboBoxItem Content = "Orange" /> 
      </ComboBox> 
		
      <TextBox  Name = "textBox" Margin = "50" Width = "100" Height = "23"
         VerticalAlignment = "Top" Text  =
         "{Binding ElementName = comboBox, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" 
         Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}"> 
      </TextBox> 
		
   </StackPanel> 
	
</Window>

Cuando ejecute la aplicación, mostrará el árbol visual en vivo donde todos los elementos se muestran en un árbol.

Este árbol visual en vivo muestra la estructura de diseño completa para comprender dónde se encuentran los elementos de la interfaz de usuario. Pero esta opción solo está disponible en Visual Studio 2015. Si está usando una opción anterior de Visual Studio, entonces no puede usar esta herramienta, sin embargo, hay otra herramienta que puede integrarse con Visual Studio como XAML Spy para Visual Studio. . Puedes descargarlo desde xamlspy