[email protected]

Asunción, PARAGUAY

Ingeniería y desarrollo de software...

29 de noviembre de 2017

Preferencias de usuario

Como el título de este artículo indica mostraré las personalizaciones que se pueden realizar en Microsoft Dynamics 365 for Operations desde la configuración del mismo.

Para poder ingresar a las preferencias del usuario es necesario seleccionar le ícono correspondiente:


Visual

A nivel visual podemos seleccionar el color de los elementos y el tamaño de los mosaicos que utilizaremos dentro del sistema:

Preferencias

Aquí se modifican las preferencias del usuario con datos que son necesarios para el manejo rápido del sistema:

Cuenta

Aquí se administra la cuenta personal de cada usuario de manera rápida y sencilla:

Flujo de trabajo

Cuando trabajamos con flujos de trabajo (workflow) es necesario configurar ciertas notificaciones, es aquí donde se las habilita:

Con estos pasos logramos personalizar elementos generales dentro de Microsoft Dynamics 365 for Operations.

Creación de espacios de trabajo

En Microsoft Dynamics 365 for Operations resulta muy sencillo crear espacios de trabajo que facilitan el acceso a distintas áreas del sistema. La diea central de un espacio de trabajo es la de tener varias opciones disponibles según las necesidades propias.

De manera predeterminada, el espacio de trabajo se ve de la siguiente manera:

Ahora bien, si necesitamos personalizar nuestra área de trabajo debemos seguir los siguientes pasos:
  1. Clic derecho en algún área disponible dentro del espacio de trabajo actual:
  2. Asignamos un nombre que nos permita identificar la nueva área de trabajo:
  3. Refrescamos la página y veremos la nueva área de trabajo en ella. Podemos hacer clic y veremos el área vacía que debemos configurar:
  4. Clic derecho en el nuevo ícono:
  5. Colocamos un nombre descriptivo al nuevo elemento (en este caso "Prueba CMASDEV"):
  6. Veremos el nuevo elemento modificado (en ocasines se necesita refrescar):
  7. Aquí debemos tener en cuenta que debemos agregar los elementos necesarios dentro de nuestra nueva área. Tal es así que debemos acceder al menú principal y seleccionar el módulo que necesitamos adicionar:
  8. Ingresamos al elemento necesario:
  9. Agregamos el módulo necesario a la vista (al área recientemente creado):
  10. Se coloca un nombre descriptivo al nuevo elemento:
  11. Por último, el área de trabajo se vería así:
Con estos pasos, hemos logrado crear un espacio de trabajo nuevo, que cumpla con nuestras necesidades.

6 de noviembre de 2017

SQL Server local en ASP.NET Core

Creamos una aplicación Web para ASP.NET Core:

Para poder comprender este ejercicio, se debe crear una clase (que representa al modelo, es decir, la tabla Persona):
using System.ComponentModel.DataAnnotations;

namespace SqlServerLocalDB.Models
{
    public class Persona
    {
        [Key]
        public int Id { get; set; }
        public string Nombre { get; set; }
        public int Edad { get; set; }
    }
}


Ahora creamos el contexto de datos para poder realizar el mapeo de la base de datos:
using Microsoft.EntityFrameworkCore;

namespace SqlServerLocalDB.Models
{
    public class PersonaContext : DbContext
    {
        public PersonaContext(DbContextOptions options)
                : base(options)
        {
        }

        public DbSet Persona { get; set; }
    }
}

Creamos la base de datos. Menú Ver > SQL Server Object Explorer.








Creamos la tabla, de manera a que quede así:

Agregamos la cadena de conexión en el archivo appsettings.json:
{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    },
    "ConnectionStrings": {
      "MovieContext": "Data Source=(localdb)\\ProjectsV13;Initial Catalog=SqlServerLocalDB;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
    }
  }
}
Con estos pasos, hemos creado el acceso a la base de datos localDB.

8 de septiembre de 2017

Instalar Microsoft Dynamics 365 Developer Toolkit

Developer Toolkit es un conjunto de herramientas de integración para Microsoft Visual Studio, enfocado a la aceleración del desarrollo de código personalizado para Microsoft Dynamics 365 (CRM).

Utilizando el toolkit, se puede crear, desarrollar e implementar plugins para Dynamics 365 (CRM), ensamblados de flujo de trabajo personalizados y recursos web sin dejar de utilizar el entorno Visual Studio.

La mejor forma de realizar la instalación es a través del Visual Studio mismo.

  1. Ir a Herramientas (Tools) > Extensiones y actualizaciones (Extensions and Updates) Extensiones de Visual Studio.
  2. Buscamos la palabra clave “Microsoft Dynamics 365 Developer Toolkit”.
  3. Instalar MD365 Developer Toolkit.
  4. Leemos los términos de la licencias y hacemos clic en “Instalar (Install)”.
  5. Se reinicia el Visual Studio y veremos la nueva plantilla instalada Plantilla Dynamics 365
Con estos pasos, hemos instalado la herramienta de productividad que estábamos necesitando.

25 de julio de 2017

Incrustar un formulario de Windows en una aplicación WPF

.NET

Formularios Windows

Se refieren a las antiguas aplicaciones ejecutadas sobre el sistema operativo Windows con una interfaz de usuario interesante pero aburrida donde no se puede salir del esquema impuesto por la plataforma.

WPF

Windows Presentation Foundation se refiere a la evolución de los formularios Windows en donde la interfaz de usuario puede ser creada a gusto del desarrollador/diseñador.

¿Cómo introducir un formulario Windows dentro de WPF?

De manera sencilla lo podemos hacer utilizando un control especializado para tal efecto el cual se denomina WindowsFormsHost, que permite introducir un formulario Windows dentro de una aplicación WPF con fines de reutilización del mismo.


Agregamos referencias a WindowsFormsIntegration y System.Windows.Forms:




Agregamos el código XAML necesario para la integración y adicionamos el control WebBrowser:
<Window x:Class="EjemploWindowsFormsHost.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:EjemploWindowsFormsHost"
        mc:Ignorable="d"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <WindowsFormsHost Name="wfh1">
            <WindowsFormsHost.Child>
                <wf:WebBrowser />
            </WindowsFormsHost.Child>
        </WindowsFormsHost>
    </Grid>
</Window>
using System.Windows;

namespace EjemploWindowsFormsHost
{
    /// 
    /// Lógica de interacción para MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            (this.wfh1.Child as System.Windows.Forms.WebBrowser).Navigate("https://www.cmasdev.net");
        }
    }
}

24 de julio de 2017

Consumo de servicio REST

En estos días, escuchamos por todos lados hablar de consumir servicios REST, el cual, se maneja a través de un protocolo muy conocido: HTTP. Esto hace que REST sea mucho más utilizado que un servicio ASMX (con protocolo SOAP). ¿Cuál prefieres?

Con la plataforma .NET, podemos crear de manera muy sencilla una WEB API que exponga los servicios REST a través del protocolo HTTP, escribiendo muy poco código. Esto escapa del objetivo de este artículo.

Para comenzar necesitamos un servicio REST publicado (vía internet o de manera local). Para este ejemplo, utilizaremos un servicio web que se encuentra disponible en la Web (al momento de escribir esta entrada el servicio se encuentra funcionando). La dirección es: http://www.groupkt.com/post/c9b0ccb9/country-and-other-related-rest-webservices.htm

En este ejemplo, necesitamos el parámetro de dos caracteres que corresponde al código del país (por ejemplo PY) y mostraremos el resultado en un Toast.

Si realizamos una prueba de servicio (pasando como parámetro PY) lo haríamos utilizando esta URL y el resultado (en formato JSON) sería:
{
  "RestResponse" : {
    "messages" : [ "More webservices are available at http://www.groupkt.com/post/f2129b88/services.htm", "Country found matching code [PY]." ],
    "result" : {
      "name" : "Paraguay",
      "alpha2_code" : "PY",
      "alpha3_code" : "PRY"
    }
  }
}
El diseño de la aplicación lo presentaremos de esta manera, en el archivo Main.axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:text="Código: "
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView1" />
    <EditText
        android:inputType="number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/codigo" />
    <Button
        android:text="Averiguar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnAveriguar" />
</LinearLayout>

¿Cómo agregar el servicio?

En este tipo de servicio no es necesario agregar referencia como lo hacíamos con los servicios ASMX, aquí se puede utilizar la clase HttpWebRequest que permite el acceso vía HTTP y obtener el resultado. A continuación se ve dicha acción en el evento btnAveriguar_Click.

Consumo del servicio

Aquí el servicio se consume de manera directa y se espera por el resultado. La clase MainActivity.cs quedaría de la siguiente manera:
using Android.App;
using Android.Widget;
using Android.OS;

namespace ServicioRest
{
    [Activity(Label = "ServicioRest", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        EditText codigo;
        Button btnAveriguar;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView (Resource.Layout.Main);

            codigo = FindViewById<EditText>(Resource.Id.codigo);
            btnAveriguar = FindViewById<Button>(Resource.Id.btnAveriguar);

            btnAveriguar.Click += btnAveriguar_Click;
        }

        private void btnAveriguar_Click(object sender, System.EventArgs e)
        {
            //Creamos la URL pasando como parámetro el código de país. Ej: PY, AR, US, ES, MX, etc.
            var url = string.Format("http://services.groupkt.com/country/get/iso2code/{0}", codigo.Text);

            //Creamos la solicitud HTTP.
            var webrequest = (HttpWebRequest)System.Net.WebRequest.Create(url);

            //Realizamos la llamada al servicio a través del protocolo HTTP.
            using (var response = webrequest.GetResponse())
            {
                //Obtenemos los datos proveídos por el servicio a través del protocolo HTTP.
                using (var reader = new StreamReader(response.GetResponseStream()))
                {
                    //Obtenemos el resultado retornado por el servicio
                    var resultado = reader.ReadToEnd();

                    //Mostramos el JSON en el Toast.
                    Toast.MakeText(this.BaseContext, resultado.ToString(),
                        ToastLength.Long).Show();
                }
            }
        }
    }
}
De esta manera, consumimos un servicio REST para utilizarlo en nuestra aplicación Xamarin.

21 de julio de 2017

Buscar Antecesor en el árbol visual

.NET Si buscamos algún elemento dentro de un objeto en la interfaz de usuario y necesitamos acceder a sus datos desde el elemento padre, pero no tenemos idea de cuántos niveles de elementos posee éste, la mejor solución es navegar a través del árbol visual hasta encontrar un elemento del tipo de dato que necesitamos.

Para eso necesitamos de una extensión de clase que permite navegar a través del árbol visual. He aquí el código:

public static class VisualTreeHelperExtensions
{
    public static T FindAncestor<T>(DependencyObject dependencyObject)
        where T : class
    {
        DependencyObject target = dependencyObject;
        do
        {
            target = VisualTreeHelper.GetParent(target);
        }
        while (target != null && !(target is T));
        return target as T;
    }
}
Cuando necesitamos obtener el elemento en cuestión simplemente utilizamos la siguiente línea:
//StackPanel es el elemento padre donde buscaremos el control y this representa al objeto actual (el hijo).
var objeto = VisualTreeHelperExtensions.FindAncestor<StackPanel>(this);
Con este sencillo código podemos navegar a través de todos los elementos dentro de un determinado objeto.

20 de julio de 2017

¿Qué versión de ASP.NET Core está instalada?

Para saber que versión de ASP.NET Core tenemos instalada en nuestra máquina se debe ejecutar esta simple línea en la ventana de comandos del Windows:
dotnet --version
El resultado será la versión que actualmente tenemos instalada en el equipo.

RelativeSource utilizando FindAncestor

.NET

RelativeSource

Es una clase que implementa una extensión de marcado la cual describe la ubicación del origen del enlace con respecto a la posición de destino del enlace.

FindAncestor

Busca elementos antecesores dentro del árbol visual establecido en RelativeSource.

Ejemplos prácticos

Si necesitas enlazarlo con otra propiedad en el objeto:
{Binding Path=PROPIEDAD_A_UTILIZAR, RelativeSource={RelativeSource Self}}

Ejemplo:
<TextBlock Width="{Binding RelativeSource={RelativeSource Self}, Path=Parent.ActualWidth}"/>
Si necesitas obtener una propiedad del antecesor:
{Binding Path=PROPIEDAD_A_UTILIZAR,
    RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TIPO_DE_DATO_DEL_ANTECESOR}}}

Ejemplo:
<TextBlock Margin="10" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}, AncestorLevel=1},Path=Name}" />
Si necesitas obtener la propiedad de una plantilla padre (aquí se muestra como utilizarlo con RelativeSource):
{Binding Path=PROPIEDAD_A_UTILIZAR, RelativeSource={RelativeSource TemplatedParent}}

Ejemplo:
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value, StringFormat=0}"/>
De esta manera hemos visto cómo trabajar con RelativeSource.

12 de julio de 2017

Cargar ListView desde una lista genérica

Cuando trabajamos con servicios Web, generalmente éste retorna listas con datos relacionados al tipo de dato que necesitamos para poder trabajar con dichos datos.

Supongamos que tenemos un servicio Web para una biblioteca donde tenemos la lista de libros y deseamos cargar dichos libros en nuestra vista dentro de la aplicación Xamarin. ¿Cómo lo hacemos?

Suscribíte al boletín