XAML en WPF C# (primera parte)

Debido a que por un momento creí que el desarrollo de aplicaciones para escritorio desaparecería en los años próximos deje de lado el XAML para Visual Studio y seguí usando las aplicaciones clásicas de Windows Forms.

Ahora leyendo literatura, Microsoft XAML junto con otras más tecnologías más hace una puesta muy interesante para unificar la vista de todas aplicaciones de Visual Studio y más allá; así que pues a entrarle no hay más. Copio y cito texto para explicar que es XAML.

XAML

“Microsoft XAML es un lenguaje de programación declarativo basado en XML. Su nombre completo es XML Application Markup Language (XAML). El lenguaje es la base para dos importantes tecnologías para desarrollar aplicaciones de Microsoft: Silverlight y Windows Presentation Foundation. ”

Windows Presentation Foundation

“WPF se introdujo con .NET 3.0 en su lugar, o al menos como un primer paso hacia estándares de la industria para utilizar lenguajes de programación declarativos tales como XML. En esencia está utilizando XML para definir un nuevo lenguaje de programación. Hasta entonces, si se necesita una aplicación de escritorio, es necesario utilizar el subsistema GDI y construir aplicaciones basadas en Windows Forms. En cambio, WPF utiliza DirectX y XAML para hacer los controles de la interfaz de usuario” [1]

No me ha costado mucho trabajo la entrada a este mundo nuevo ya que si se sabe usar los Windows Form, los controles son muy parecidos aunque con algunas variaciones.

Aquí describiré una de las cosas que no me salieron a la primera búsqueda de Google.

Para crear una aplicación de XAML para escritorio se hace lo siguiente en Visual Studio 2017.

Vamos a Archivo – Nuevo – Proyecto. En el dialogo elegimos:

Se tarda un poco en la creación del proyecto y al final nos muestra una ventana, aquí muestro un prototipo de la aplicación de la cartera de clientes para los compañeros de “Desarrollo de aplicaciones I”.

Muy parecido a los Windows Form, pero podemos ver algunos detalles, vamos a las propiedades por ejemplo:

Aquí un ejemplo de los cambios con Windows Form, una etiqueta la propiedad para anotar texto era Text, en XAML es Content, como se puede observar. A continuación tenemos el código XAML.

<Window x:Class=”WpfAppClients.MainWindow”
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″
xmlns:local=”clr-namespace:WpfAppClients”
mc:Ignorable=”d”
Title=”Customer Portfolio” Height=”350″ Width=”701″>

<Grid Margin=”0,0,2,0″>

<Label Content=”Customer number:” HorizontalAlignment=”Left” Margin=”28,37,0,0″ VerticalAlignment=”Top” RenderTransformOrigin=”-9.67,-2.955″/>
<TextBox x:Name=”Txt_Number” HorizontalAlignment=”Left” Height=”23″ Margin=”159,40,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”73″ IsEnabled=”False”/>
<Label Content=”First name:” HorizontalAlignment=”Left” Margin=”28,68,0,0″ VerticalAlignment=”Top” RenderTransformOrigin=”-9.67,-2.955″/>
<TextBox x:Name=”Txt_FirstName” HorizontalAlignment=”Left” Height=”23″ Margin=”159,72,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”317″ IsEnabled=”False”/>
<Label Content=”Last name:” HorizontalAlignment=”Left” Margin=”28,99,0,0″ VerticalAlignment=”Top” RenderTransformOrigin=”-9.67,-2.955″/>
<TextBox x:Name=”Txt_LastName” HorizontalAlignment=”Left” Height=”23″ Margin=”159,102,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”317″ IsEnabled=”False”/>
<Label Content=”Phone number:” HorizontalAlignment=”Left” Margin=”29,130,0,0″ VerticalAlignment=”Top” RenderTransformOrigin=”-9.67,-2.955″/>
<TextBox x:Name=”Txt_phonenumber” HorizontalAlignment=”Left” Height=”23″ Margin=”159,133,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”120″ IsEnabled=”False”/>
<Label Content=”City:” HorizontalAlignment=”Left” Margin=”29,168,0,0″ VerticalAlignment=”Top” RenderTransformOrigin=”-9.67,-2.955″/>
<ComboBox x:Name=”Cmb_City” HorizontalAlignment=”Left” Margin=”159,172,0,0″ VerticalAlignment=”Top” Width=”228″ IsEnabled=”False”>

<ComboBoxItem Content=”New York”/>
<ComboBoxItem Content=”San Francisco”/>
<ComboBoxItem Content=”Los Angeles”/>
<ComboBoxItem Content=”Chicago”/>

</ComboBox>
<Image x:Name=”Img_photo” HorizontalAlignment=”Left” Height=”131″ Margin=”560,25,0,0″ VerticalAlignment=”Top” Width=”100″ IsEnabled=”False”/>
<Button x:Name=”Bt_Nuevo” Content=”New” HorizontalAlignment=”Left” Margin=”62,253,0,0″ VerticalAlignment=”Top” Width=”75″ RenderTransformOrigin=”-1.813,-0.4″ Click=”Bt_Nuevo_Click”/>
<Button x:Name=”Bt_Save” Content=”Save” HorizontalAlignment=”Left” Margin=”165,253,0,0″ VerticalAlignment=”Top” Width=”75″ RenderTransformOrigin=”-1.813,-0.4″ Click=”Bt_Save_Click”/>
<Label x:Name=”Lbl_datos” Content=”Label” HorizontalAlignment=”Left” Margin=”62,283,0,0″ VerticalAlignment=”Top”/>
<Button x:Name=”Bt_upload” Content=”Upload photo” HorizontalAlignment=”Left” Margin=”564,179,0,0″ VerticalAlignment=”Top” Width=”96″ RenderTransformOrigin=”0.88,1.05″ Click=”Bt_upload_Click”/>

</Grid>

</Window>

He aquí como la tecnología web impera hoy por hoy en el mundo del desarrollo de software. Entonces al igual que en windows form, si damos dobles clicks en los controles se lanza el template del evento más común de dicho control. Aquí el código por ejemplo del botón para invocar al OpenFileDialog.

private void Bt_upload_Click(object sender, RoutedEventArgs e)
{

Microsoft.Win32.OpenFileDialog ofdPhoto =
new Microsoft.Win32.OpenFileDialog();
ofdPhoto.Filter = “Image Files (*.bmp, *.jpg)|*.bmp;*.jpg”;
ofdPhoto.ShowDialog();
if (ofdPhoto.FileName != string.Empty)
{

BitmapImage bmiPhoto = new BitmapImage();
bmiPhoto.BeginInit();
bmiPhoto.UriSource = new Uri(ofdPhoto.FileName);
bmiPhoto.EndInit();
Img_photo.Source = bmiPhoto;

}

}

 

Supongo  que al ser una tecnología nueva hay pocas cosas en la red al respecto de XAML, yo agarrado de mi ego pensaba “es lo mismo” y me fui a la barra de herramientas y después de varias revisiones no encontré nada parecido al OpenFileDialog. Y de nuevo a navegar en la web, como menciono no hay mucho en la red, y mi ex-alumna Laura creo me compartió un manual (voy a buscarlo). Total que me encontré 2 referencias interesantes.

En la primera que me dio luz sobre equivalencias es una de las páginas de Microsoft donde se hace una comparativa entre Windows Form y XAML (Wfp). [2] Y después el buen Joaquín Medina Serrano hace un ejemplo de lo que necesitamos para nuestro caso, codificado en Visual Basic pero de mucha utilidad. [3]

Si leemos el artículo de Microsoft nos dice que hacemos un wrapper de la clase Microsoft.Win32.OpenFileDialog para utilizarlo en XAML, y esta página nos muestra como utilizarla también, con un pequeño ejemplo, sus propiedades y métodos. [4]

Mencionaré que yo valido el que el usuario me haya proporcionado un archivo de imagen y su correspondiente ruta, preguntando por la propiedad FileName, sin embargo en el artículo lo hace de la siguiente forma:

Nullable<bool> result = dlg.ShowDialog();

if (result == true)

{

// Open document string filename = dlg.FileName;

}

Sigamos extendiendo, vamos dando una pequeña entrada al modelo MVC por lo que vamos a agregar una clase llamada Customer y para ello hacemos una carpeta llamada Model, y vamos desarrollando la clase. (NOTA – Ustedes van a encontrar que VS tiene el motor RAZOR para hacer MVC sin tanta complicación)

Una caraterística interesante para los que son nuevos en la OOP, es como podemos sobrescribir el método ToString(), que todos los objetos heredan y para darle nuestra propia funcionalidad se agrega la palabra override.

Así mismo la vista lo es solo para mostrar datos así que tenemos el método AssignValues() que recibe la forma completa y luego se rescatan los valores para asignarlos a la clase.

Ahora regresamos a la forma  en el código correspondiente a C#. Al crear la carpeta el namespace cambia por lo que para usar la clase Customer, tenemos que agregar el using correspondiente a ese namespace.

using WpfAppClients.Model;

En el botón “Save” programamos la invocación al objeto.

private void Bt_Save_Click(object sender, RoutedEventArgs e)
{

Customer MyCust = new Customer();
MyCust.AssignValues(this);
Lbl_datos.Content = MyCust.ToString();
CleanTheText();
EnabledAndDisabled(false);

}

Podemos observar que mandamos this, que es la forma (formulario) que estamos trabajando y en el método de la clase asignamos los valores de los controles a los atributos de la clase.

Después de varias horas, voy a hacerme a la idea que poner una imagen a un control Image por medio de su url es unidireccional, y que teniendo el Image ya cargado con la imagen, no se puede obtener de vuelta la url :), por lo que como buen programador de antaño, hacemos el plan b, a la clase pongo la propiedad vUrlImage.

public partial class MainWindow : Window
{
public string vUrlImage { set; get;}

Y a la hora de cargar la imagen, asigno a esta propiedad el atributo FileName de la clase OpenFileDialog

bmiPhoto.UriSource = new Uri(ofdPhoto.FileName);
bmiPhoto.EndInit();
Img_photo.Source = bmiPhoto;
vUrlImage = ofdPhoto.FileName;

Por último ahora si guardamos en la clase esta propiedad que nos faltaba.

PhoneNumber = long.Parse(wind.Txt_phonenumber.Text);
CodeCity = wind.Cmb_City.Text;
UrlImage = wind.vUrlImage;

Y con esto ya tenemos la vista lista o casi lista.

En la segunda entrega mandaremos los datos a una base de datos.

Hasta la próxima.

Atte.

Profesor Miguel Araujo.

Webgrafía.

[1] abcarticulos Artículos libres “Microsoft Aplicaciones Basada en XAML”

http://abcarticulos.info/article/microsoft-aplicaciones-basada-en-xaml

[2] Página de Microsoft, “Windows Forms Controls and Equivalent WPF Controls”

https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/windows-forms-controls-and-equivalent-wpf-controls

[3] La Güeb de Joaquín Medina Serrano , “Wpf – Carga una imagen en el control wpf image”

http://joaquin.medina.name/web2008/documentos/informatica/lenguajes/puntoNET/System/Windows/Controls/Wpf_Image/2016_01_10_CargaImagen.html

[4] Página de Microsoft, “OpenFileDialog Class”

https://docs.microsoft.com/en-us/dotnet/api/microsoft.win32.openfiledialog?view=netframework-4.7.1

Deja un comentario