Archivo de la etiqueta: VB.NET

Temas relacionados con Visual Basic para .NET Framework

Cambiar el tamaño de los controles de un formulario automáticamente

Pues eso… que lo que publiqué anteayer sobre ajustar automáticamente la fuente de un formulario según la configuración del sistema (Cambiar automáticamente las fuentes de nuestro formulario a las de Windows), estaba muy bien, pero no era lo que yo andaba buscando… yo lo que quería era que los controles también cambiaran.

La batallita del Guille

Y me puse a ello… como soy un poquillo torpe, ya sabes, no tengo estudios informáticos ni de otros tipos, pues… empecé a escribir el código para cambiar cada uno de los controles del formulario, y por supuesto también el del formulario, ahí si llego ;-). Sí, lo hice, escribí todo el código, con métodos recursivos, etc. En fin… :-/

La cuestión es que pensé que también estaría guay (cool) poder cambiar las fuentes, así todo estaría más grande… o más pequeño, ya que en el formulario de prueba (ver figura 1) puse la opción de ampliar o reducir.

Figura 1. La aplicación en modo inicial (usando la configuración del usuario de Windows)
Figura 1. La aplicación en modo inicial (usando la configuración del usuario de Windows)

Pero aquello era un caos, cuando ampliaba, lo hacía según el ancho y el alto y claro, si los controles no tienen todos los Anchor necesarios, pues… se te quedaba espacio vacío por aquí y por allá… no tengo capturas (¡gracias a Dios! si no, ya no vendrás más a visitarme 😛 )

Con decirte que hice hasta una clase para que manejase el tema este del cambio de los controles y así hacerlo más cool… con un evento que indicaba que se estaban haciendo los cambios, etc.; sí, lo que yo te diga, en fin…

Bueno, vale… otro día hago la captura y así ves cómo se puede uno embrollar con lo que después resultó ser algo muy simple de codificar.

La solución (muy fácil y sencilla)

Pues eso, la solución, para esto de que se cambien los controles de tamaño según indiquemos, es muy simple, tanto que… bueno… mejor me callo… ¡ay zeñó!

Y todo surgió porque los controles quedaban muy mal al cambiar el tamaño, y me dio por probar (esto aún podría estar en la batallita del Guille, pero bueno…) quitando el cambio del tamaño del formulario y de los controles, y dejar solo el cambio del tamaño de la fuente y… ¡voilà, todo va a la perfección!. No sabes la de cabezazos que me hubiera dado contra la pared… menos mal que ahora me he pelado al 2 y no era plan… 🙂

Te muestro un par de capturas con el 25% de ampliación y el 50% para que te hagas una idea de lo bien que funciona 🙂 y después te muestro el código tanto para Visual Basic como para C#.

Figura 2. Aspecto de la aplicación en funcionamiento usando el 25% de ampliación
Figura 2. Aspecto de la aplicación en funcionamiento usando el 25% de ampliación
Figura 3. Aspecto de la aplicación en funcionamiento usando un 50% de ampliación
Figura 3. Aspecto de la aplicación en funcionamiento usando un 50% de ampliación

Nota:
Según parece, la imagen 1 y 2 son iguales, pero si te fijas en la figura 3, en la que muestro el IDE de Visual Studio, comprobarás que el tamaño del formulario es significativamente más grande que el mostrado en el diseñador de VS.

Pulsa en las imágenes para verlas en grande.

El código para cambiar el tamaño de los controles de un formulario

Comentarte que todo está en cambiar el tamaño de la fuente del formulario, por tanto debes tener asignado el valor Font a la propiedad AutoScaleMode del formulario (es el valor predeterminado al crear un nuevo formulario).

El código para Visual Basic

'--------------------------------------------------------------------------
' Métodos para cambiar el tamaño del formulario
' y de sus controles
'--------------------------------------------------------------------------

''' <summary>
''' Cambia el tamaño del formulario (o control) indicado,
''' ampliando o reduciendo según un porcentaje.
''' Recomendado es solo cambiar el formulario.
''' </summary>
Private Sub cambia(ctr As Control, ampliar As Boolean, por As Integer)
    If ampliar = False Then
        por = -por
    End If

    '----------------------------------------------------------------------
    ' El ancho y alto es mejor no cambiarlo,
    ' las proporciones de los controles se verán bien
    ' pero si el Anchor no está "pensado" para todos
    ' los controles, quedarán espacios vacíos con
    ' respecto al diseño original.
    ' Al cambiar la fuente del formulario,
    ' el aspecto original no se pierde.
    '----------------------------------------------------------------------


    '----------------------------------------------------------------------
    ' Al cambiar el tamaño de la fuente del formulario
    ' los controles se adaptan al nuevo tamaño de fuente,
    ' sin perder el aspecto del diseño original.
    '
    ' El formulario debe tener asignada la propiedad
    ' AutoScaleMode = Font
    '----------------------------------------------------------------------

    '
    ' Se debería poner un máximo y mínimo a las fuentes
    '

    Dim fntSize = ctr.Font.Size
    fntSize = calculaPorcentaje(fntSize, por)

    ' No admitir valores menores de uno
    ' ni valores mayores de 3 veces la fuente
    If fntSize < 1 OrElse fntSize > ctr.Font.Size * 3 Then
        fntSize = ctr.Font.Size
    End If

    ctr.Font = New Font(ctr.Font.FontFamily,
                        fntSize, ctr.Font.Style,
                        ctr.Font.Unit, ctr.Font.GdiCharSet,
                        ctr.Font.GdiVerticalFont)
End Sub

''' <summary>
''' Calcula el porcentaje a partir de un valor Single,
''' para el tamaño de la fuente.
''' </summary>
Private Function calculaPorcentaje(valor As Single, porcentaje As Integer) As Single
    Return valor + (valor * porcentaje / 100)
End Function

El código para C#

// --------------------------------------------------------------------------
// Métodos para cambiar el tamaño del formulario
// y de sus controles
// --------------------------------------------------------------------------

/// <summary>
/// Cambia el tamaño del formulario (o control) indicado,
/// ampliando o reduciendo según un porcentaje.
/// Recomendado es solo cambiar el formulario.
/// </summary>
private void cambia(Control ctr, bool ampliar, int por)
{
    if (ampliar == false)
        por = -por;

    // ----------------------------------------------------------------------
    // El ancho y alto es mejor no cambiarlo,
    // las proporciones de los controles se verán bien
    // pero si el Anchor no está "pensado" para todos
    // los controles, quedarán espacios vacíos con
    // respecto al diseño original.
    // Al cambiar la fuente del formulario,
    // el aspecto original no se pierde.
    // ----------------------------------------------------------------------


    // ----------------------------------------------------------------------
    // Al cambiar el tamaño de la fuente del formulario
    // los controles se adaptan al nuevo tamaño de fuente,
    // sin perder el aspecto del diseño original.
    // 
    // El formulario debe tener asignada la propiedad
    // AutoScaleMode = Font
    // ----------------------------------------------------------------------

    // 
    // Se debería poner un máximo y mínimo a las fuentes
    // 

    var fntSize = ctr.Font.Size;
    fntSize = calculaPorcentaje(fntSize, por);

    // No admitir valores menores de uno
    // ni valores mayores de 3 veces la fuente
    if (fntSize < 1 || fntSize > ctr.Font.Size * 3)
        fntSize = ctr.Font.Size;

    ctr.Font = new Font(ctr.Font.FontFamily, fntSize, 
                        ctr.Font.Style, ctr.Font.Unit, 
                        ctr.Font.GdiCharSet, ctr.Font.GdiVerticalFont);
}

/// <summary>
/// Calcula el porcentaje a partir de un valor Single,
/// para el tamaño de la fuente.
/// </summary>
private float calculaPorcentaje(float valor, int porcentaje)
{
    return valor + (valor * porcentaje / 100);

}

Al método cambia le pasamos el control o formulario (recomendable el formulario) en el que queremos hacer el cambio de tamaño, el valor de ampliar es si queremos ampliar (true) o reducir (false) y por es el porcentaje, que es un valor entero y puede ser 0 (cero) para no hacer nada o dejarlo como estaba, o cualquier otro tamaño (no te recomiendo un valor mayor de 175 si no, pues… te faltará pantalla… 🙂

Como puedes comprobar, he puesto una comprobación para que el tamaño de la fuente no sea menor de 1 ni mayor de 3 veces el tamaño inicial.
Si quieres cambiarlo, hazlo, pero al menos deja la comprobación de que no sea menor de uno (o cero) ya que so es cero (0) te dará error.

Y ahora pasemos al código que he usado para cambiar el tamaño del formulario y sus controles.

El código de ejemplo para cambiar el tamaño según un porcentaje

En el ejemplo que he hecho (ver cualquiera de las figuras) he puesto la opción de Ampliar o Reducir, un combo con los porcentajes a usar y el botón Cambiar para aplicar el cambio.

También he puesto un botón para restaurar el tamaño al inicial (Restablecer fuente) pero en realidad no es necesario, ya que al indicar 0% se deja todo como estaba al inicio.

Lo que si hago es que ese porcentaje sea fijo, es decir, siempre que pulses en, por ejemplo, 50% se cambiará al 50% del valor inicial.

Te aclaro esto porque inicialmente (ya sabes: la torpeza del Guille) ese porcentaje lo aplicaba al valor que ya hubiese de antes, por tanto, si inicialmente lo habías ampliado al 10% y después seleccionabas el 50% este último se aplicaba sobre la ampliación (o reducción) anterior, y… bueno, que no quedaba nada bien.

Para conseguir esto, que siempre se aplique el porcentaje según la fuente inicial, he creado una variable llamada miWinFont, esa es la fuente que tiene el sistema, ya que he usado el mismo código que te mostré en el artículo anterior (Cambiar automáticamente las fuentes de nuestro formulario a las de Windows) para utilizar la fuente indicada en Windows.

La asignación de esa variable se hace al inicio del programa (en el constructor) y después se usa para reiniciar el tamaño de la fuente antes de hacer el cambio, ahora lo verás en el código.

Como tip te puedo decir que puedes usar otra forma de hacerlo, por ejemplo usando el valor de fntSize a partir del valor de miWinFont en vez de la fuente del formulario, pero no he cambiado el código porque eso se me acaba de ocurrir mientras escribo el artículo, y ya no es plan de cambiar el código 😉

Vamos a lo que vamos.

Empecemos con el código de Visual Basic, pero tanto en el de VB como en el de C# lo que hago es lo mismo: hacer el cambio usando el evento Click del botón Cambiar.

El código para Visual Basic de los métodos de evento

'
' Los métodos de evento para el cambio de la fuente
'
Private Sub btnCambiarTamaño_Click(sender As Object, e As EventArgs) Handles _
                                            btnCambiarTamaño.Click
    ' Cambiar solo el tamaño de la fuente del formulario
    txtInfo.Text = "Cambiando el tamaño de los controles..."
    Application.DoEvents()

    Me.Hide()

    ' restablecer a la fuente inicial
    Me.Font = miWinFont

    ' hacer el cambio de tamaño
    cambia(Me, optAmpliar.Checked, CInt(cboTamaños.SelectedItem))

    Me.Show()

    txtInfo.Text = "Cambiado el tamaño de los controles."
    Application.DoEvents()
End Sub

Private Sub btnRestablecerFuente_Click(sender As Object, e As EventArgs) Handles _
                                                btnRestablecerFuente.Click
    ' Restablecer siempre a la fuente del sistema
    ' si no queremos usar la del sistema,
    ' asignar al valor de miFuente (la original al diseñar)
    Me.Font = miWinFont


End Sub

Ahora después te muestro dónde declaro miWinFont y dónde la asigno.

El código para C# de los métodos de evento

//
// Los métodos de evento para el cambio de la fuente
//

private void btnCambiarTamaño_Click(object sender, EventArgs e)
{
    // Cambiar solo el tamaño de la fuente del formulario
    txtInfo.Text = "Cambiando el tamaño de los controles...";
    Application.DoEvents();
    this.Hide();
    
    // restablecer a la fuente inicial
    this.Font = miWinFont;
    
    // hacer el cambio de tamaño
    cambia(this, optAmpliar.Checked, Convert.ToInt32(cboTamaños.SelectedItem));

    this.Show();
    txtInfo.Text = "Cambiado el tamaño de los controles.";
    Application.DoEvents();

}

private void btnRestablecerFuente_Click(object sender, EventArgs e)
{
    // Restablecer siempre a la fuente del sistema
    // si no queremos usar la del sistema,
    // asignar al valor de miFuente (la original al diseñar)
    this.Font = miWinFont;

}

Este es el código donde se define y se asigna miWinFont.

Adivina cuál es el de VB y cuál el de C# 😉

Public Class Form1
    ''' <summary>
    ''' La fuente del sistema
    ''' </summary>
    Private miWinFont As Font

[...]

'
' El constructor del formulario
'
Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    miFont = Me.Font

    Me.Font = SystemFonts.IconTitleFont
    AddHandler SystemEvents.UserPreferenceChanged,
                AddressOf SystemEvents_UserPreferenceChanged
    miWinFont = Me.Font

    infoFuentes()
End Sub

'
' Los métodos de evento para interactuar con la configuración de Windows
'
Private Sub SystemEvents_UserPreferenceChanged(ByVal sender As Object,
                                               ByVal e As UserPreferenceChangedEventArgs)
    If e.Category = UserPreferenceCategory.Window Then
        Me.Font = SystemFonts.IconTitleFont
        miWinFont = Me.Font
    End If

    mostrarInfoForm()
    txtInfo.Text = String.Format("UserPreferenceChanged.Category = {0} ({1:HH:mm:ss}){2}{3}",
                                 e.Category.ToString(), Date.Now,
                                 Microsoft.VisualBasic.vbCrLf,
                                 txtInfo.Text)

End Sub
public partial class Form1 : Form
{
    /// <summary>
    /// La fuente del sistema
    /// </summary>
    private Font miWinFont;

[...]

//
// El constructor del formulario
//
public Form1()
{

    // This call is required by the designer.
    InitializeComponent();

    // Add any initialization after the InitializeComponent() call.
    miFont = this.Font;

    this.Font = SystemFonts.IconTitleFont;
    SystemEvents.UserPreferenceChanged +=
                                SystemEvents_UserPreferenceChanged;
    this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

    // Para que tenga dos m\f2étodos de evento el evento Load
    this.Load += new System.EventHandler(this.Form1_Load);

    miWinFont = this.Font;

    infoFuentes();
}

//
// Los métodos de evento para interactuar con la configuración de Windows
//

private void SystemEvents_UserPreferenceChanged(object sender,
                                        UserPreferenceChangedEventArgs e)
{
    if (e.Category == UserPreferenceCategory.Window) {
        this.Font = SystemFonts.IconTitleFont;
        miWinFont = this.Font;
    }

    mostrarInfoForm();
    txtInfo.Text = string.Format("UserPreferenceChanged.Category = {0}"+
                                 "({1:HH:mm:ss}){2}{3}",
                                 e.Category.ToString(), DateTime.Now,
                                 "\r\n", txtInfo.Text);

}

Nota:
No te preocupes por la definición de los métodos infoFuentes ni mostrarInfoForm, ese código está en el ZIP que te pondré al final con el código completo.

Y esto es todo… ya ves qué simple… 🙂

Espero que te sea de utilidad, ¡’esa es siempre la idea!

Nos vemos.
Guillermo.

P.S.
Comentarte que en el código completo (sí, para VB y C#) la aplicación lo que hace es permitir que selecciones un fichero (archivo) y te muestre las propiedades, nombre completo, directorio, fecha de creación, etc.

El código completo del ejemplo (solución para Visual Studio usando .NET 4.7.2)

El ZIP con el código completo (una solución de Visual Studio 2017 con los proyectos de Visual Basic y C#

ZIP: Cambiar tamaño controles.zip (254 KB)

MD5 Checksum: 0B5DDD8A525D61647F10070EFC198DCA

P.S. 2 (31/Dic/18)
Aquí tienes un ejemplo de cómo hacer que el resto de formularios de nuestra aplicación utilicen el tamaño asignado en el formulario principal:
Interceptar el cambio del tamaño de los controles de un formulario en otros formularios de la aplicación.

Cambiar automáticamente las fuentes de nuestro formulario a las de Windows

Pues eso… que como ahora “ando liado” con dos monitores, uno, el principal en el portátil (laptop) y el segundo uno de más resolución, pues… resulta que quiero que en el monitor se vean las fuentes más grandes y también el formulario y los controles, y antes de empezar a hacer “manualidades” (adaptar las cosas por la cuenta de la vieja, es decir, a mano) me he decidido a buscar en Internet a ver si había algo y resulta que sí, que lo hay (o casi), seguramente habrá más cosas pero lo que en principio me ha parecido una buena opción es lo que he encontrado en Cómo: Responder a los cambios de las combinaciones de fuentes en una aplicación de Windows Forms, concretamente en la sección: Para usar la fuente del escritorio y responder a los cambios de esquema de fuentes y concretamente el código mostrado en: Para cambiar manualmente la combinación de fuentes en Windows XP.

Por supuesto el código de ejemplo solo se muestra en C#, pero… no te preocupes aquí estoy yo para mostrarte cómo hacer eso que ahí dice en Visual Basic .NET (sí, y también en C# 😉 )

El código básicamente es como está en esa página que te he indicado, lo único que yo he añadido al ejemplo que te voy a poner es la opción de mostrar las fuentes originales (iniciales del formulario) o bien usar las que Windows te indique.

Para que te hagas una idea de lo que el código hace, te muestro dos capturas del formulario (Form1) en ejecución, la figura 1 es con las letras “normales” y la segunda captura (figura 2) es usando el código que hace que se adapte a las fuentes de Windows.

Nota:
Este código solo cambia el tamaño de las fuentes del formulario, no la de los controles.
Al cambiar la fuente del formulario, este cambia también de tamaño y “reubica los controles”.

 

El formulario usando las fuentes normales
Figura 1. El formulario con las fuentes normales


El formulario usando las fuentes de Windows
Figura 2. El formulario usando las fuentes de Windows

No te asustes porque haya muchos controles 😉

Es que ese formulario lo tengo para hacer unas pruebas para convertir de Windows Forms a WPF / XAML y tengo que probar con prácticamente todos los controles (al menos los que yo suelo usar), lo que importa es que veas que el formulario de la figura 2 ha cambiado de tamaño y también el contenido de algunos de los controles (salvo los menús y la barra de botones).


No te voy a explicar en detalle cómo funciona esto, ya que en la página que te indiqué ya lo hacen 🙂 pero si te voy a mostrar el código necesario para que funcione así.


Si estás usando Visual Basic tendrás que agregar el código del constructor (Sub New) (el IDE de Visual Studio agrega el contenido necesario de forma automática) y añadimos las siguientes líneas de código después de la llamada a InitializeComponent:

El código de Visual Basic para el constructor (Sub New):

Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

    Me.Font = SystemFonts.IconTitleFont
    AddHandler SystemEvents.UserPreferenceChanged, AddressOf SystemEvents_UserPreferenceChanged

End Sub

El código de C# para el constructor:

public Form1()
{
    InitializeComponent();

    this.Font = SystemFonts.IconTitleFont;
    SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
    this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
}

Si te fijas un poco, en el código de VB no he puesto el “manenejador de eventos” para el evento Form.Closing, ya que no es necesario, aunque se podría haber hecho como en C#, pero si Visual Basic facilita la creación de eventos, ¿por qué no usarla? (ya sabes, en la declaración del evento se añade la cláusula Handles y a continuación el nombre del evento a “capturar”.


Te explico brevemente lo que hace ese código del constructor:

Asigna a la fuente del formulario la que hay definida en Windows, esto funciona desde Windows XP hasta el actual Windows 10 (actual en las fechas que estoy escribiendo esto, es decir el 27 de diciembre de 2018).


Después añade el manejador de eventos para la clase UserPreferenceChanged de SystemEvents, que es una clase definida en el espacio de nombres Microsoft.Win32, por tanto en el formulario hay que importar ese espacio de nombres, ya sabes:
Imports Microsoft.Win32 para Visual Basic o using Microsoft.Win32; para C#.


En C# también añade el controlador de eventos para el evento Form.Closing.


En realidad en el evento Form.Closing solo se desliga el manejador de eventos para UserPreferenceChanged.

Aquí tienes el código para VB y C#.

El código para Visual Basic:

Private Sub SystemEvents_UserPreferenceChanged(ByVal sender As Object,
                                               ByVal e As UserPreferenceChangedEventArgs)
    If e.Category = UserPreferenceCategory.Window Then
        Me.Font = SystemFonts.IconTitleFont
    End If
End Sub

Private Sub Form1_FormClosing(ByVal sender As Object,
                              ByVal e As FormClosingEventArgs) Handles Me.FormClosing
    RemoveHandler SystemEvents.UserPreferenceChanged,
            AddressOf SystemEvents_UserPreferenceChanged
End Sub

 

El código para C#:

void SystemEvents_UserPreferenceChanged(object sender, 
                                        UserPreferenceChangedEventArgs e)
{
    if (e.Category == UserPreferenceCategory.Window)
    {
        this.Font = SystemFonts.IconTitleFont;
    }
}

void Form1_FormClosing(object sender, 
                       FormClosingEventArgs e)
{
    SystemEvents.UserPreferenceChanged -= 
        new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);
}

Y esto es todo amigo 🙂


Si me decido a poner algún ejemplo completo, actualizaré esta “entrada” (o post) poniendo el enlace para la descarga.



Espero que te sirva 😉

Nos vemos.
Guillermo

P.S.
Si quieres que los controles de tu formulario cambien
al tamaño que tu indiques (un porcentaje), mira esta entrada:
Cambiar el tamaño de los controles de un formulario automáticamente

Números aleatorios con decimales en .NET

Pues eso… aquí te explicaré cómo generar números aleatorios con decimales y cómo indicar los valores entre los que quieres que estén esos números usando la clase Random de .NET y con ejemplos tanto para Visual Basic .NET como para C# (e incluso para BASIC, bueno… al menos para Visual Basic 6.0 y anteriores).

Pero primero te contaré la “batallita del Guille” para que sepas el porqué a estas alturas de la vida te explico algo tan “elemental” Winking smile

Si no te quieres leer la batallita, pues… pasa un poco más abajo que ahí te muestro el código de ejemplo tanto para Visual Basic .NET como para C# e incluso para VB6.

La batallita del Guille

Estaba yo el otro día escribiendo un código en el que necesitaba generar dos números aleatorios (en realidad varios).
Dos de ellos eran números enteros, en esos no tuve mayor problema, ya que tenía este artículo publicado en mi sitio: Random.Next ese incomprendido  y me lo leí, y todo a la perfección… Winking smile

El problema me surgió al crear los números aleatorios con decimales.
Yo sabía que usando NextDouble de la clase Random era como tenía que hacerlo (la certeza era porque yo lo decía al final del artículo ese que te he comentado en el párrafo anterior Winking smile).
Y curiosamente en ese mismo comentario decía que lo más parecido a la función Rnd() de Visual Basic 6.0 era precisamente NextDouble.
Pero… ¿quieres creerte que ya no me acordaba cómo se usaba la función RND de BASIC? jajajaja, en fin… seguramente serán cosas de la edad o de que en los últimos años no tengo la programación como una de mis tareas diarias… en fin…

La cuestión es que volvía a buscar en la web (indicando elGuille) cómo usar RND o casi… y me encontré como mi Curso Básico de Programación en Visual Basic, concretamente en las soluciones de la décima entrega, lo explicaba… ¡menos mal que el Guille aún mantiene su sitio después de los 22 años que cumplió hace pocos días! Winking smile

Generar un número aleatorio con decimales entre dos cifras

El método NextDouble genera un número que será igual o mayor que 0.0 y menor (pero no igual) que 1.0.
Por tanto si lo multiplicaras, por ejemplo por 6, generaría un valor que iría desde 0.0 a 5.99.

Nota:
En Visual Basic 6.0 (o incluso en VB.NET y si me apuras hasta en C#) se utilizará la función Rnd para hacer el mismo papel que NextDouble, pero con valores de tipo Single en lugar de Double.

Tal como explico en las respuestas del curso básico, si quieres un número entero entre 20 y 50 debes escribir un código como este (este ejemplo es de VB6, las variables están declaradas en otra parte… supongo)

T = Int(Rnd * 31) + 20 ‘Número de rascadas, T valdrá de 20 a 50

Es decir la función Rnd (o el método NextDouble) debes multiplicarlo por  31 (50-20+1) y después añadirle el mínimo (20). De esa forma se genera el rango de valores que queremos usar.
En ese ejemplo se usa la función Int para convertir el resultado en un número entero, pero recuerda que ¡es código de VB6!

Ahora veremos ese mismo ejemplo pero haciendo las cosas bien y con .NET.

El código de ejemplo

El siguiente código creará un número aleatorio (con decimales) entre 20 y 50 (ambos incluidos).

Inserta este código en el método Main de una aplicación de consola.

Código para Visual Basic .NET

Dim r As New Random()

Dim minimo As Integer = 20
Dim maximo As Integer = 50

Dim res = (r.NextDouble() * (maximo - minimo + 1)) + minimo
Console.WriteLine("Un número Double entre {0} y {1} (incluidos)", minimo, maximo)
Console.WriteLine("(r.NextDouble * ({0} - {1} + 1)) + {1} = {2}", maximo, minimo, res)
Console.WriteLine()

Console.ReadLine()

Código para C#

var r = new Random();

int minimo = 20;
int maximo = 50;

var res = (r.NextDouble() * (maximo - minimo + 1)) + minimo;
Console.WriteLine("Un número Double entre {0} y {1} (incluidos)", minimo, maximo);
Console.WriteLine("(r.NextDouble * ({0} - {1} + 1)) + {1} = {2}", maximo, minimo, res);
Console.WriteLine();

Console.ReadLine();

La salida mostrada será algo así:

numeros_aleatorios_vb_02
Figura 1. Salida del código de ejemplo

Casualmente el número generado aleatoriamente es 50 y pico… para que veas que el máximo también se incluye Smile

Resumiendo

Para generar un número entre dos valores (ambos incluidos) usa el cálculo siguiente:

(r.NextDouble() * (maximo – minimo + 1)) + minimo

o este otro que también hace lo mismo:

(r.NextDouble() * (minimo – maximo)) + maximo

Resaltar aquí, que si quieres la misma funcionalidad que el método Next de la clase Random, es decir que el valor generado sea igual o mayor que mínimo pero menor que máximo tendrías que hacerlo de esta forma:

(r.NextDouble() * (maximo – minimo)) + minimo

Para finalizar, recordarte que le eches un vistazo a las explicaciones que doy en el artículo que te indiqué al principio:
Random.Next ese incomprendido

Espero que te sirva Winking smile

Nos vemos.
Guillermo

ejemplo de ExecuteScalar para leer una columna de una tabla

 

Pues eso… que esto seguro que lo tengo mil veces publicado en mi sitio, pero hoy lo he ido a buscar, y no lo he encontrado de forma concreta, así que… aquí está para que "yo" lo encuentre… jejeje

¿Por qué buscaba esto?

El caso es el siguiente: necesitaba saber el ID (u otro campo) de una tabla de una base de datos de SQL Server Express 2014 (el tipo de base de datos es indiferente siempre que tenga el método que te comento) haciendo una consulta, concretamente usando LIKE en la propia cadena de selección o consulta.

La consulta es la siguiente:

String.Format( "SELECT ID FROM Clientes WHERE Nombre LIKE '%{0}%' AND Apellidos LIKE '%{1}%'",

nombre, apellidos)

No indico la forma de asignar esa cadena para que uses VB o C#, en el primer caso tendrías que indicar Dim sel = y en el segundo var sel =

A continuación creamos un objeto del tipo Connection y otro del tipo Command y hacemos una llamada al método ExecuteScalar y el valor que devuelva será (en este caso concreto) el ID que estamos buscando o CERO si no lo ha encontrado.

Simplificando (sin tratamiento de error y esas cosas), si el acceso a la base de datos es de SQL Server (en este ejemplo en una instancia de SQLEXPRESS) y usamos las clases definidas en System.Data.SqlClient, el código sería algo así:

Visual Basic:

Public Shared Function BuscarCliente2(nombre As String, apellidos As String) As Integer
    Dim elID As Integer = 0

    Dim sel =
        String.Format(
            "SELECT ID FROM Clientes WHERE Nombre LIKE '%{0}%' AND Apellidos LIKE '%{1}%'",
            nombre, apellidos)

    Dim sCon = ".\sqlexpress;Initial Catalog=LaBaseDeDatos;Integrated Security=True"

    Using con As New SqlConnection(sCon)
        Dim cmd As New SqlCommand(sel, con)

        con.Open()

        elID = CInt(cmd.ExecuteScalar())

        con.Close()
    End Using

    Return elID
End Function

 

C#:

public static int BuscarCliente2(string nombre, string apellidos)
{
    int elID = 0;

    var sel =
        String.Format(
            "SELECT ID FROM Clientes WHERE Nombre LIKE '%{0}%' AND Apellidos LIKE '%{1}%'",
            nombre, apellidos);

    var sCon = @".\sqlexpress;Initial Catalog=LaBaseDeDatos;Integrated Security=True";

    using (SqlConnection con = new SqlConnection(sCon))
    {
        SqlCommand cmd = new SqlCommand(sel, con);

        con.Open();

        elID = Convert.ToInt32(cmd.ExecuteScalar());

        con.Close();
    }

    return elID;
}

 

Y esto es todo amigos… 🙂

 

Nos vemos.

Guillermo

Las novedades de C# 6 y Visual Basic 14 con ejemplos de sus desarrolladores

 

Pues eso… aquí te dejo los enlaces a las novedades de C# 6 y Visual Basic 14 con ejemplos de los team de desarrollo que han hecho posible esas novedades y aunque ya llevan publicados algunos meses he creído conveniente recordártelo ya que dentro de pocos días será la presentación oficial de Visual Studio 2015 (al menos la versión RC o Release Candidate o versión candidata la que será la versión final).

novedades c# y vb

Por tanto… -voy a darle un toque circense o de espectáculo, que es de lo que se trata-

Señoras y señores, ante ustedes de la mano del C# Team las nuevas características de C# 6: New Features in C# 6.

Y el más difícil todavía, intentar que el lenguaje más usado del mundo mundial siga en la brecha (a la vanguardia o más o menos) y hacer lo que parecía el más difícil todavía: conseguir que aún sea más potente sin dejar de ser fácil de usar, sin más delación y de la mano del Visual Basic Team, las nuevas características que encontrarás en Visual Basic 14: New Language Features in Visual Basic 14.

Y esto ha sido todo por hoy… espero que hayas disfrutado del espectáculo. 🙂

 

Nos vemos.
Guillermo

¡Feliz día del libro!

 

Pues eso… 23 de abril, un día después de que muriera Cervantes… jum! yo siempre tenía entendido que era un día como hoy cuando dejó su cuerpo y por eso lo de la "festividad", pero bueno… ¡fiesta! 🙂

Tengo un regalito para ti en este día… sí, y es relacionado con los libros:

Mis dos libros electrónicos publicados con SolidQ Press sobre las novedades de los lenguajes de .NET, uno de Visual Basic .NET y el otro de C#.

Aquí te dejo los enlaces a las correspondientes páginas en mi sitio (elguille.info) y de ahí te los puedes descargar… aunque sean de hace tres o cuatro versiones, seguro que aún te sirven… sí, sí, te lo digo yo… 😉

El libro del Guille con las novedades de Visual Basic:

Novedades de Visual Basic 9.0

 

El libro del Guille con las novedades de C#:

Aprenda C# 3.0 desde 0.0 (parte 3, lo nuevo)

Nota:
Esos links te llevan a las páginas correspondientes en mi sitio, más que nada para que sepas que por ahí puedes ver más cosas sobre Visual Basic y C# (muuuuchas más cosas) y después te traerán aquí de nuevo (al blog) que es donde realmente están los enlaces que en su día publiqué jeje.

Valeee… este es el enlace aquí en mi blog; es que no puede ser… siempre haces lo que quieres conmigo… jajaja

Mis libros electrónicos GRATIS

 

¡Espero que te sean de utilidad! y recuerda… el botón ese de "Donar" está para que lo uses… ¡no te cortes! y así me puedes ayudar… que no tengo un chavo/duro/centavo y… pues eso… 😉

Gracias.

Nos vemos.
Guillermo

probar varias cadenas de conexión si una da error, y no morir en el intento

 

Pues eso… que estaba modificando/probando la aplicación esa que en su día te comenté para acceder a los ficheros de FoxPro (o dBase) con la extensión DBF y resulta que me dio error al conectar a la base de datos, concretamente este:

ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified

Así que… me fui a ver mi artículo (Acceso a ficheros dBase (.dbf) desde Visual Basic .NET y C#) y usé otra cadena de conexión (todo esto después de probar a instalar los drivers de VFP -que por cierto me equivoqué e instalé y los de OLEDB en vez de los de ODBC porque no encontré los drivers de este último… y ¡me lié! po zí…  pero bueno, ese es otro tema… jum!).
La cuestión es que tuve que desinstalar los drivers de OLEDB ya que la cadena de conexión y el tipo de datos que quería usar eran los de ODBC.

Nota aclaratoria del 23/Abr/2015 11:15
Aparte de agregar un nuevo comentario al párrafo anterior, quiero aclararte que:
Busqué los drivers de ODBC (que son los que yo quería utilizar) y por error me bajé los de OLEDB y después de instalarlos y probar “con la conexión ODBC” de que no funcionaba -lógico, no son los adecuados- desinstalé los drivers de OLEDB y usé una cadena de conexión diferente que en mi equipo sí funcionaba (sin los drivers de VFP), pero no en el equipo de mi amigo que aún tenía los drivers de VFP que en su día instaló…

Para tu información la cadena que inicialmente estaba usando (y la que funciona en el equipo de mi colega) es esta:

"Driver={Microsoft Visual FoxPro Driver};
SourceType=DBF;
SourceDB=" & sBase & ";"

Y la otra que probé y a mi sí me funcionó es esta otra:

"Driver={Microsoft dBASE Driver (*.dbf)};
DriverID=277;
Dbq=" & sBase & ";"

La cuestión es que la de Visual FoxPro Driver a mi no me iba y la de dBASE driver no le iba a mi colega Manolo (le da el error de la figura 1).

error dBASE en equipo Manolo

Figura 1. Error del controlador/driver dBASE

Así que… tenía que hacer algo para usar uno en un equipo y otro en el otro… y antes de ponerme a saber el nombre del equipo y demás, me dije… jum! esta vez voy a probar primero lo más simple y después ya veré si me tengo que complicar la vida con otras cosas.

Y lo más simple para mi es: ¡probar si puede conectar con una cadena de conexión y si no puede, entonces probar otra! y…

(Ahora, al escribir esto último me recuerda mis tiempos de programador de Quick BASIC y el uso y "mal uso" de ON ERROR RESUME NEXT o lo que es lo mismo: si se produce un error que continúe girando el mundo… ¡hasta que se pare! jaja… en fin…)

Y eso he hecho y eso es lo que me funciona, mi colega aún no lo habrá probado, pero seguro que a él también le funciona; así que… si funciona… ¡todos contentos! 🙂

(y sobre todo, él puede seguir trabajando, yo no, pero él sí jeje)

Y este es el código que he usado (por ahora en Visual Basic .NET ya que mis proyectos los suelo hacer siempre para Visual Basic -salvo excepciones).

 

El código de la función LeerBases(path) para Visual Basic .NET

Public Shared Function LeerBases(ByVal dirDBF As DirectoryInfo) As DataSet
    Datos = New DataSet

    Dim sBase As String = dirDBF.FullName
    Dim sConn As String

    Dim ficsDbf() As FileInfo = dirDBF.GetFiles("*.dbf")
    If ficsDbf.Length = 0 Then Return Datos

    ' Utilizar varias conexiones y probar con las siguientes si da error (14/Abr/15)
    Dim cadenasConexión() As String = {"Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" & sBase & ";",
                                       "Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=" & sBase & ";"}

    Dim intentosConexion As Integer = 0
    Dim hayError As Boolean = False
    Dim mensajeError As String = ""

    Do
        sConn = cadenasConexión(intentosConexion)

        Using dbConn As New System.Data.Odbc.OdbcConnection(sConn)
            Try
                dbConn.Open()

                For Each fi As FileInfo In ficsDbf
                    Dim sSelect As String = "SELECT * FROM " & fi.Name

                    Dim da As New System.Data.Odbc.OdbcDataAdapter(sSelect, dbConn)
                    Dim dt As New DataTable

                    da.Fill(dt)
                    If dt.Rows.Count > 0 Then
                        Datos.Tables.Add(dt)
                    End If
                Next

                dbConn.Close()

                hayError = False

                ' Salir del bucle,
                ' no sea que haya más opciones de conectar y no es plan...
                Exit Do

            Catch ex As Exception
                mensajeError = _
                    "Error al abrir la base de datos" & vbCrLf &
                    ex.Message & vbCrLf &
                    "Usando: '" & cadenasConexión(intentosConexion) & "'"
                hayError = True

                ' Este es el mensaje de error que me muestra:
                ' ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified
            End Try
        End Using

        intentosConexion += 1
    Loop While intentosConexion < cadenasConexión.Length

    If hayError Then
        System.Windows.Forms.MessageBox.Show(mensajeError,
                                             "Error al conectar a los datos de DBF",
                                             System.Windows.Forms.MessageBoxButtons.OK,
                                             System.Windows.Forms.MessageBoxIcon.Exclamation)
    End If

    Return Datos
End Function


 

Y esto es todo amigos… 🙂

Espero que te sea de utilidad y que si así lo es, me invites a un té o un refresco… y como va a ser complicado que nos veamos para esa invitación (y no es plan de esperar a que eso ocurra en otra vida), puedes invitarme usando el botón de Donar ese que tengo en mi blog, allí, arriba a la derecha o en mi sitio, sí, ese que está allí arriba, donde dice eso de Donativo para el sitio de elGuille.

Gracias.

 

Nos vemos.

Guillermo

Este artículo también está publicado en mi sitio:

http://www.elguille.info/NET/ADONET/probar-varias-cadenas-de-conexion-si-una-da-error-y-no-morir-en-el-intento.aspx

( En realidad obtiene el contenido desde aquí, de mi blog 🙂 )

como conectar a una base de datos de MySQL en un servidor Web desde .NET

 

Pues eso… hace unos días he estado haciendo una pequeña aplicación para acceder a una base de datos de MySQL creada en un servidor web de Domitienda y voy a aprovechar para comentarte las cosillas que he hecho (como conectar a una BBDD de MySQL, enviar emails, obtener datos de tres tablas diferentes pero que había que relacionar para sacar lo que interesaba, etc.) y la primera fue lo más importante: Conectar con una base de datos de MySQL con Visual Basic .NET (o .NET en general).
Y esto es lo que te voy a contar en este "artículo" de hoy lunes 13 de abril de 2015.

Los requisitos

Lo primero que deberías hacer es descargarte la DLL (librería/biblioteca) de MySQL para usar con Visual Studio, bueno, en realidad lo que yo me iba a bajar el Connector .NET, concretamente la versión 6.9.6 porque decía que la versión 6.7 el Connector/Net no incluye el "MySQL for Visual Studio integration", así que ni me puse a "investigar" a qué se refería, por tanto me bajé el MySQL for Visual Studio, concretamente la versión web community 5.6.23.0 (a la hora de escribir esto está la versión 5.6.24.0).

Nota:
El descargar la versión "web community" es porque tenía conexión a internet y así solo tenía que descargar 1.6MB frente a los 286,7MB de la versión off-line.

Es un MSI installer y te da un montón (o dos o tres o cuatro, pal caso es lo mismo) de opciones, pero solo usé la del Connector o lo que pusiera en las opciones de instalación.

 

Añadir la referencia de MySql.Data al proyecto

Una vez instalado, en el proyecto desde el que quieras acceder a la base de datos de MySQL le agregas la referencia correspondiente.
En mi caso usé la versión 4.5 ya que el proyecto también usaba el .NET Framework 4.5 (ver la figura 1).

MySqlData referencia
Figura 1. Referencia al ensamblado de MySql.Data versión 6.9.5

Y una vez que hemos agregado la referencia al ensamblado MySql.Data ya podemos acceder a las clases de conexión y demás, que están en el espacio de nombres MySql.Data.MySqlClient.

Y el resto… como de costumbre… pero no te preocupes te voy a poner el código (primero para VB y después para C#) de cómo usar la conexión y acceder a una tabla y demás, pero eso será… ¡ma-ña-na! 🙂

Bueno, vale, al menos te pondré el código de cómo conectar a la base de datos.

 

Conectar a la base de datos de MySQL desde Visual Basic .NET

Yo suelo usar un método en una clase con métodos compartidos (en VB puedes usar un módulo, pero yo uso una clase para después convertir fácilmente el código a C#), el método es una función llamada CadenaConexion que devuelve una cadena con la cadena de conexión generada por la clase ConnectionStringBuilder, en realidad la clase se llama MySqlConnectionStringBuilder, pero si has usado conexión a SQL Server sabrás que en ese caso el nombre es SqlConnectionStringBuilder.

Para poder acceder a las clases de MySql.Data debes añadir una importación de espacios de nombres a MySql.Data.MySqlClient:

' Para Visual Basic:
Imports MySql.Data.MySqlClient

// Para C#:
using MySql.Data.MySqlClient;

Y esta es la definición del método que está en una clase (class) de VB y por eso el método lo he definido como Shared (static en C#) para que lo puedas usar simplemente anteponiendo el nombre de la clase y sin necesidad de crear nuevas instancias ni nada de eso:

El código del método CadenaConexion para Visual Basic:

''' <summary>
''' La cadena de conexión a la base de datos
''' </summary>
Public Shared Function CadenaConexion() As String
    Dim csb As New MySqlConnectionStringBuilder
    csb.Server = "mysql3.servidoreswindows.net"
    csb.Database = "nombre_Base_Datos"
    csb.UserID = "nombre_usuario_de_la_base"
    csb.Password = "la_clave_del_usuario_de_la_base"
    csb.IntegratedSecurity = False

    Return csb.ConnectionString
End Function

El método CadenaConexion para C#:

/// <summary>
/// La cadena de conexión a la base de datos
/// </summary>
public static string CadenaConexion()
{
    MySqlConnectionStringBuilder csb = new MySqlConnectionStringBuilder();
    csb.Server = "mysql3.servidoreswindows.net";
    csb.Database = "nombre_Base_Datos";
    csb.UserID = "nombre_usuario_de_la_base";
    csb.Password = "la_clave_del_usuario_de_la_base";
    csb.IntegratedSecurity = false;

    return csb.ConnectionString;
}

 

Y esto es todo por hoy… mañana (seguramente)… más… 😉

 

Nos vemos.

Guillermo

Este artículo también está publicado en mi sitio:

http://www.elguille.info/NET/ADONET/MySQL_CadenaConexion.aspx

( En realidad obtiene el contenido desde aquí, de mi blog 🙂 )

Si comparas fechas, mejor usa TimeSpan en vez de Substract

 

Pues eso… estaba haciendo unas comprobaciones para mostrar un aviso después de pasado cierto tiempo, por ejemplo, si han pasado varias horas o minutos entre dos fechas, concretamente entre una fecha almacenada y la otra la fecha y hora actual.

Lo que en un principio se me ocurrió es hacer uso del método Substract de la clase DateTime (también Date para Visual Basic) y mirar si, por ejemplo, había al menos una diferencia de 5 minutos, algo así:

VB:

If fecha1.Subtract(fecha2).Minutes > 5 Then

C#:

if (fecha1.Subtract(fecha2).Minutes > 5)

El problema es que esto solamente comprueba si en la información de los minutos de las dos fechas hay esa diferencia una vez que a los minutos de la fecha2 se le resten los minutos de la fecha1.

Sí, está claro, así es como debe funcionar.

Pero ¿qué pasa si los minutos no se diferencian en 5 pero la fecha completa (fecha1) es mayor que la otra (fecha2) en al menos un día (o solo una hora)?

Pasa que Substract falla.

Si lo que en realidad queremos es comprobar si entre dos fechas ha pasado cierto periodo de tiempo, por ejemplo los 5 minutos de este ejemplo, pero comprobando las fechas y horas al completo, (es decir, si ha pasado más de un día, quiere decir que ha pasado más de 5 minutos), entonces deberíamos usar TimeSpan.

Este es el código a usar:

VB:

' con TimeSpan tiene en cuenta la fecha completa
Dim tsMinutos As New TimeSpan(0, 5, 0)
Dim tsDif = fecha1.Subtract(fecha2)
If tsDif > tsMinutos Then
    bAvisado = True
End If

 

C#:

// con TimeSpan tiene en cuenta la fecha completa
TimeSpan tsMinutos = new TimeSpan(0, 5, 0);
var tsDif = fecha1.Subtract(fecha2);
if (tsDif > tsMinutos)
{
    bAvisado = true;
}

 

Captura usando estas dos fechas:

fecha1 = New DateTime(2014, 11, 19, 16, 26, 0)

fecha2 = New DateTime(2010, 10, 12, 7, 26, 0)

Comparar_DateTime

 

Y esto es todo…

Si quieres ver el código al completo (aplicación de consola) tanto para Visual Basic como para C#, sigue este enlace a mi sitio de descargas:

Fichero con el código de ejemplo.

Nombre: Comparar_DateTime.zip

Tamaño: 21,3 KB

MD5 checksum: 78025D0A1B2DE530C46735E5288A4071

 

Nos vemos

Guillermo

Cómo usar el FileOpenPicker para seleccionar ficheros en las apps de Windows Store

 

Pues eso… ahora le toca el turno al FileOpenPicker el "seleccionador" de ficheros en las aplicaciones de la Tienda de Windows.

En las aplicaciones para la Tienda de Windows (Windows Store) esta es la única forma (que yo conozco) de acceder a una carpeta local (o de la red o de un disco extraíble o de un sistema de almacenamiento como Skydrive) y seleccionar un fichero.

Aunque antes hay que indicarle a la aplicación de que queremos acceder a esos sitios, para ello tendremos que abrir el fichero de manifiesto de la aplicación (Package.appxmanifest) y en la ficha Capabilities (ver figura 1) indicar que queremos utilizar el Private Networks y Removable Storage (por si queremos acceder a un disco externo/conectado por USB).

 

FileOpenPicker 02
Figura 1. Indicar las "Capabilities" de la aplicación

 

Lo siguiente que tenemos que hacer es indicar en la ficha Declarations que queremos usar el File Open Picker.

 

FileOpenPicker 03
Figura 2. En Declarations indicamos que queremos usar el File Open Picker

 

Tal como vemos en la figura 2 tenemos que indicar al menos un tipo de fichero (Supported file type) aunque no tiene porqué ser el mismo tipo que vamos a usar, en este ejemplo he indicado ".xml" y casualmente voy a buscar ese tipo de fichero, pero como veremos en el código, también voy a indicar que me muestre los que tengan la extensión .txt (además de los .xml).

La forma de usar ese control es desde dentro de un método asíncrono (async) ya que las llamadas a los métodos para acceder al fichero son llamadas asíncronas.

En el siguiente código vemos lo que necesitamos para usar esa clase. Dependiendo del tipo de ficheros a los que queramos acceder así lo indicaremos en la colección FileTypeFilter, en este ejemplo he añadido dos tipos: .xml y .txt, pero si quisiéramos acceder a todos los tipos, habría que indicar el asterisco (*), en el ejemplo el asterisco está comentado, pero si quieres hacer pruebas, quita el comentario.

Este es el código de Visual Basic, el de C# está más abajo.

Dim openPicker As New FileOpenPicker()
openPicker.FileTypeFilter.Add(".xml")
openPicker.FileTypeFilter.Add(".txt")
'openPicker.FileTypeFilter.Add("*")
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary
openPicker.ViewMode = PickerViewMode.List
Dim cfgFile As StorageFile = Await openPicker.PickSingleFileAsync()

If cfgFile Is Nothing Then Exit Sub

Dim sr = New StreamReader(Await cfgFile.OpenStreamForReadAsync)

 

Utilizando ese código podremos ver algo como la captura de la figura 3.

FileOpenPicker 01

Figura 3. El FileOpenPicker en acción

 

Y esto es prácticamente todo… aquí te dejo el código de ejemplo de C# para que no te quejes si prefieres los puntos y comas 😉

FileOpenPicker openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add(".xml");
openPicker.FileTypeFilter.Add("*");
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.ViewMode = PickerViewMode.List;
StorageFile cfgFile = await openPicker.PickSingleFileAsync();

if (cfgFile == null) return;

var sr = new StreamReader(await cfgFile.OpenStreamForReadAsync());

 

Comentarte que la clase FileOpenPicker está definida en Windows.Storage.Pickers y la clase StorageFile está definida en Windows.Storage.

Y esto ya si que es todo…

Nos vemos.

Guillermo