Mostrando entradas con la etiqueta CSharp. Mostrar todas las entradas
Mostrando entradas con la etiqueta CSharp. Mostrar todas las entradas

jueves, 10 de julio de 2014

Formatear un texto a XML

Para formatear un texto en el cual tengamos un archivo XML, para que quede con la estructura
del archivo XML, podemos implementar la siguiente clase que recibe como parámetro el texto:
 
public static String PrintXML(String XML)
{
   String Result = "";

   MemoryStream mStream = new MemoryStream();
   XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode);
   XmlDocument document   = new XmlDocument();

try
{
   //Cargamos el XmlDocument con el XML que tenemos en DatosXml
   document.LoadXml(DatosXml);

   writer.Formatting = Formatting.Indented;

   //Formateamos el contenido del documento con el XmlTextWriter
   document.WriteContentTo(writer);
   writer.Flush();
   mStream.Flush();

   //Tengo que rebobinar la MemoryStream para leer su contenido.
   mStream.Position = 0;

   //Almacenamos en un StreamReader el contenido del MemoryStream
   StreamReader sReader = new StreamReader(mStream);

   //Extraemos el texto del StreamReader.
   Result = sReader.ReadToEnd();

   mStream.Close();
   writer.Close();
}
catch (XmlException)
{
}
return Result;
}

viernes, 21 de marzo de 2014

Setear error en las filas de un grid Devexpress

Para validar la información de un registro y si no pasa dicha validación setear el icono del error en la fila y columna del registro, hacemos algo como lo estamos haciendo en el siguiente ejemplo:

* La clase que estamos utilizando como fuente de datos, la heredamos de IDXDataErrorInfo

public class Person : object, IDXDataErrorInfo {
        public Person(string firstName, string lastName, string address, string phoneNumber, string email) {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Address = address;
            this.PhoneNumber = phoneNumber;
            this.Email = email;
        }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
        public string PhoneNumber { get; set; }
        public string Email { get; set; }

        #region IDXDataErrorInfo Members
        void IDXDataErrorInfo.GetPropertyError(string propertyName, ErrorInfo info) {
            switch(propertyName) {
                case "FirstName":
                case "LastName":
                    if(IsStringEmpty(propertyName == "FirstName" ? FirstName : LastName)) {
                        SetErrorInfo(info, propertyName + " field can't be empty", ErrorType.Critical);
                    }
                    break;
                case "Address":
                    if(IsStringEmpty(Address)) {
                        SetErrorInfo(info, "Address hasn't been entered", ErrorType.Information);
                    }
                    break;
                case "Email":
                    if(IsStringEmpty(Email)) {
                        SetErrorInfo(info, "Email hasn't been entered", ErrorType.Information);
                    } else if(Email != "none" && !IsEmailCorrect(Email)) {
                        SetErrorInfo(info, "Wrong email address", ErrorType.Warning);
                    }
                    break;
            }
        }
        void IDXDataErrorInfo.GetError(ErrorInfo info) {
            if(IsStringEmpty(PhoneNumber) && (Email == "none" || !IsEmailCorrect(Email)))
                SetErrorInfo(info, "Either Phone Number or Email should be specified", ErrorType.Information);
        }
        #endregion
        bool IsStringEmpty(string str) {
            return str == null || str.Trim().Length == 0;
        }
        bool IsEmailCorrect(string email) {
            return email == null || (email.IndexOf("@") >= 1 && email.Length > email.IndexOf("@") + 1);
        }
        void SetErrorInfo(ErrorInfo info, string errorText, ErrorType errorType) {
            info.ErrorText = errorText;
            info.ErrorType = errorType;
        }

jueves, 27 de febrero de 2014

StopWatch en C#

Una instancia de Stopwatch puede medir el tiempo transcurrido para un intervalo o el total de tiempo transcurrido entre varios intervalos. En un escenario de Stopwatch habitual, se llama al método Start, en otro momento se llama al método Stop y, por último, se comprueba el tiempo transcurrido mediante la propiedad Elapsed.
Una instancia de Stopwatch se está ejecutando o está detenida; utilice IsRunning para determinar el estado actual de Stopwatch. Utilice Start para empezar a medir el tiempo transcurrido; utilice Stop para detener la medida del tiempo transcurrido. Consulte el valor de tiempo transcurrido a través de las propiedades Elapsed, ElapsedMilliseconds o ElapsedTicks. Puede consultar las propiedades de tiempo transcurrido mientras la instancia se está ejecutando o mientras está detenida. Las propiedades de tiempo transcurrido aumentan continuamente mientras se ejecuta Stopwatch; permanecen constantes cuando la instancia está detenida.
De manera predeterminada, el valor de tiempo transcurrido de una instancia de Stopwatch es igual al total de todos los intervalos de tiempo medidos. Cada llamada a Start inicia la cuenta del tiempo transcurrido acumulado; cada llamada a Stop finaliza la medición del intervalo actual y bloquea el valor de tiempo transcurrido acumulado. Utilice el método Reset para borrar el tiempo transcurrido acumulado en una instancia de Stopwatch existente.
Stopwatch mide el tiempo transcurrido contando pasos del temporizador en el mecanismo de temporización subyacente. Si el hardware instalado y el sistema operativo admiten un contador de rendimiento de alta resolución, la clase Stopwatch utiliza ese contador para medir el tiempo transcurrido. De lo contrario, la clase Stopwatch utiliza el temporizador del sistema para medir el tiempo transcurrido. Utilice los campos Frequency y IsHighResolution para determinar la precisión y la resolución de la implementación de control de tiempo de Stopwatch.
La clase Stopwatch ayuda en la manipulación de contadores de rendimiento relacionados con el control de tiempo dentro del código administrado. Específicamente, el campo Frequency y el método GetTimestamp pueden utilizarse en lugar de QueryPerformanceFrequency y QueryPerformanceCounter de las API Win32 no administradas. Ejemplo sencillo:
 
Stopwatch sw = new Stopwatch();
            sw.Start();
            sw.Stop();
 
Fuente 

domingo, 2 de febrero de 2014

Controles WPF

  • ComboBox 
Este control, muestra una fuente de datos en un componente desplegable tipo ItemsControl. Para tener un correcto funcionamiento cuando la fuente de datos, por ejemplo una entidad, se debe tener en cuenta lo siguiente:
    • ItemsSource = puede ser un Binding a una clase.
    • DisplayMemberPath="Description" 
    • SelectedValuePath="Code"
    • SelectedValue = un Binding a una propiedad de la clase.
 Cuando necesitamos crear un ComboBox de multiple selección con Devexpress:
<dxe:ComboBoxEdit x:Name="checkedComboBox" ItemsSource="{Binding FiltersMV.Shifts}" ShowSizeGrip="False" IsTextEditable="False" ShowCustomItems="True" MinWidth="100">
    <dxe:ComboBoxEdit.StyleSettings>
        <dxe:CheckedComboBoxStyleSettings />
    </dxe:ComboBoxEdit.StyleSettings>
</dxe:ComboBoxEdit>


  • TimeSpan
Para trabajar con horas y validar si una hora esta en un rango de horas de varias fechas, podemos utilizar este control y realizar dichas validaciones:

//Fecha actual
DateTime currentDate = Servinte.Clinic.Core.Reads.ProxyHelper.CurrentDate();               
////Horario actual
TimeSpan CurrentShift = new TimeSpan(currentDate.Hour, currentDate.Minute, currentDate.Second);
//Configuracion del turno de la Mañana
TimeSpan ShiftMornig = new TimeSpan(Convert.ToInt32(VariablesKardex.VariablesConfiguration.NursingShiftStartTimeMorning.Value.ConfigValue.Substring(0, 2)), Convert.ToInt32(VariablesKardex.VariablesConfiguration.NursingShiftStartTimeMorning.Value.ConfigValue.Substring(3, 2)), 0);
//Configuracion del turno de la tarde
TimeSpan ShiftAfternoon = new TimeSpan(Convert.ToInt32(VariablesKardex.VariablesConfiguration.NursingShiftStartTimeAfternoon.Value.ConfigValue.Substring(0, 2)), Convert.ToInt32(VariablesKardex.VariablesConfiguration.NursingShiftStartTimeMorning.Value.ConfigValue.Substring(3, 2)), 0);
//Configuracion del turno de la noche
TimeSpan ShiftNight = new TimeSpan(Convert.ToInt32(VariablesKardex.VariablesConfiguration.NursingShiftStartTimeNight.Value.ConfigValue.Substring(0, 2)), Convert.ToInt32(VariablesKardex.VariablesConfiguration.NursingShiftStartTimeMorning.Value.ConfigValue.Substring(3, 2)), 0);

//Turno que seleccionaremos por defecto
ShiftDefaul = TimeSpan.Compare(CurrentShift, ShiftMornig) >= 0 && TimeSpan.Compare(CurrentShift, ShiftAfternoon) < 0 ? ShiftDefaul = FiltersMV.Shifts.Where(w => w.Code.Equals("MA")).FirstOrDefault() :
    TimeSpan.Compare(CurrentShift, ShiftAfternoon) >= 0 && TimeSpan.Compare(CurrentShift, ShiftNight) < 0 ? FiltersMV.Shifts.Where(w => w.Code.Equals("TA")).FirstOrDefault() :
    ShiftDefaul = FiltersMV.Shifts.Where(w => w.Code.Equals("NO")).FirstOrDefault();

  •  Comando de MVVM para un evento
Para bindear un comando de una ViewModel, a un evento de un control de la vista, realizamos lo siguiente:

<ListBox Name="employeeListBox" ItemsSource="{Binding empList}" Grid.Row="0" SelectedItem="{Binding SelectedIndex}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <i:InvokeCommandAction Command="{Binding MyCommand}" CommandParameter="{Binding ElementName=employeeListBox, Path=SelectedValue}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListBox>


  •  Binding de una propiedad MVVM a un DataTemplate
Para bindear una propiedad de la ViewModel a un DataTemplate, realizamos lo siguiente:
<DataTemplate>
    <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.ErrorMessageDate }"/>
</DataTemplate>


  •  Realizar bloqueo en tabla
Para guardar información en la base de datos y requerimos primero bloquear la tabla, realizamos lo siguiente:
try
{
   transaction = database.BeginTransaction();               
   if(!database.LockTable(transaction, "HHACTPRO", "ACTPROSUO", string.Format(" actprosuo = {0} and actprospo = {1}", param["1"], param["2"], param["3"]), true))
         throw new ApplicationException("La reprogramación del registro esta siendo modificada por otro usuario. En el momento no se puede procesar esta acción");
                
   int detailResult = database.ExecuteNonQuery(sql, transaction, parameters);
   transaction.Commit();

}
catch(Exception ex)
{
    transaction.Rollback();
    throw;
 }


  •  Obtener la secuencia de una tabla
Para consulta la última secuencia de una tabla para realizar un insert, realizamos lo siguiente:

//Consultamos la siguiente secuencia del registro que vamos a insertar, para eso utilizamos la funcion GetAutonumeric(). ESto solo para ORACLE
if (BaseRuntime.ProviderName.Equals("Oracle"))
{
    sequence = db.GetAutonumeric("sq_hfrevord_sec", transaction);
    param.Add(sequence, DbType.Int64);                                       
}

//Consultamos la última secuencia del registro insertado en la tabla, para esto utilizamos la función. Esto para cualquier motor menos ORACLE
if (!BaseRuntime.ProviderName.Equals("Oracle"))
{
    sequence =  db.GetLastSerial("hfrevord", transaction);                                       
    param.Add(sequence, DbType.Int64);
}


  •  Generar un evento de doble clic en un control con MVVM
Para generar un evento de doble clic en un control lo realizamos con el siguiente código:

//Agregamos el namespace que necesitaremos en el trigger, y el DataContext es la VM
xmlns:spc="clr-namespace:Servinte.Presentation.Core;assembly=Servinte.Presentation.Core"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
 
<Grid>
<i:Interaction.Triggers>
    <spc:DoubleClickTrigger>
        <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}, Path=DataContext.ConsultOrderInformationCommand}" CommandParameter="{Binding OrderTreatment}"/>
    </spc:DoubleClickTrigger>
</i:Interaction.Triggers>
</Grid>


  • Mascara para un textedit devexpress
Para construir un control que solo permita ingresar números, con un determinado número de decimales, utilizamos la mascara. Este es el código de ejemplo:

//Agregamos la mascara con #,###,### para indicar que máximo puede ingresar 7 enteros y .## dos decimales
 
<dxe:TextEdit Name="txtPrice" Text="{Binding AmountRegister}" MinHeight="30" MaskType="Numeric" MaskUseAsDisplayFormat="True" Mask="#,###,###.##" HorizontalContentAlignment="Right" />

  • Validacion en un control devexpress
Para realizar una validación en un control de devexpress, realizamos lo siguiente:

//Agregamos la propiedad Validate y el método que va a realizar la validación de los datos. Las otras propiedades de validación es para permitir dejar el control con el error y validar al momento de digitar los datos.
 
<dxe:TextEdit Name="txtAmountRegister" Text="{Binding AmountRegister}" Validate="txtAmountRegister_Validate" InvalidValueBehavior="AllowLeaveEditor" ValidateOnTextInput="False" IsEnabled="{Binding IsEnableRegister, Converter={StaticResource boolToVisibilityConverter},ConverterParameter=AmountRegister}" MinHeight="30" MaskType="Numeric" MaskUseAsDisplayFormat="True" Mask="###,###.0" HorizontalContentAlignment="Right" MaskAutoComplete="Optimistic">

  • Line de separador
Para pintar una linea de separador en la interface de WPF, se realiza lo siguiente:

//Debemos asegurarnos que el namespace x, ya este invocado en el archivo con el siguiente código: 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Luego agregamos la siguiente línea en el código XAML:
 
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />

  • Rotar texto en un control
Para rotar el texto de un control, podemos realizar lo siguiente:

<TabControl TabStripPlacement="Left">
    <TabItem Header="Tab 1">
        <TabItem.LayoutTransform>
            <RotateTransform Angle="-90"></RotateTransform>    
        </TabItem.LayoutTransform>
        <TextBlock> Some Text for tab 1</TextBlock>
    </TabItem>
    <TabItem Header="Tab 2">
        <TabItem.LayoutTransform>
            <RotateTransform Angle="-90"></RotateTransform>
        </TabItem.LayoutTransform>
        <TextBlock> Some Text for tab 2</TextBlock>
    </TabItem>
</TabControl>


  • Bindear el evento load de un control
Para bindear el evento load de un control, a un método del ViewModel, realizamos lo siguiente:

//Debemos asegurarnos que el namespace x, ya este invocado en el archivo con el siguiente código: 
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Luego agregamos el código XAML en el control:
 
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding MyICommandThatShouldHandleLoaded}" />
    </i:EventTrigger>
</i:Interaction.Triggers>


//En la viewModel debemos crear un ICommand, para enlazarlo a este.

  • Creación de tramas
Para crear tramas y pintarlas en un control, por ejemplo como background, realizamos lo siguiente:

//Primero debemos crear como recurso la trama de VisualBrush, para luego llamarla desde la propiedad del componente.
 
<VisualBrush x:Key="DiagonalLeftLines" TileMode="Tile" Viewport="0,0,20,1" ViewportUnits="Absolute" Viewbox="0,0,10,10" ViewboxUnits="Absolute">
    <VisualBrush.RelativeTransform>
        <RotateTransform Angle="-45" CenterY="0.5" CenterX="0.5"/>
    </VisualBrush.RelativeTransform>
    <VisualBrush.Visual>
        <Canvas>
            <Path Stroke="Red" Data="M 4 0 l 0 10" StrokeThickness="1"  />
        </Canvas>
    </VisualBrush.Visual>
</VisualBrush>
<VisualBrush x:Key="DiagonalRightLines" TileMode="Tile" Viewport="0,0,20,1" ViewportUnits="Absolute" Viewbox="0,0,10,10" ViewboxUnits="Absolute">
    <VisualBrush.RelativeTransform>
        <RotateTransform Angle="45" CenterY="0.5" CenterX="0.5"/>
    </VisualBrush.RelativeTransform>
    <VisualBrush.Visual>
        <Canvas >
            <Path Stroke="Red" Data="M 4 0 l 0 10" StrokeThickness="1"  />
        </Canvas>
    </VisualBrush.Visual>
</VisualBrush>


//En la interface gráfica, hacemos el enlace desde la propiedad al recurso de la trama: 
<TextBlock Text="{Binding}" Background="{StaticResource DiagonalLeftLines}" TextTrimming="CharacterEllipsis" TextWrapping="Wrap"/>

Interface INotifyPropertyChanged

  • Framework 4.5      
 public event PropertyChangedEventHandler PropertyChanged;

        private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "")
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                var handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));
                }
            }
        }

  • Framework < 4.5
public event PropertyChangedEventHandler PropertyChanged;

private void RaisePropertyChanged(string propertyName)
        {
            // take a copy to prevent thread issues
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

miércoles, 3 de abril de 2013

¿Cómo se puede formatear cadenas de texto?


Cuando tenemos un texto y hacemos lo siguiente:
Console.WriteLine("La cantidad de dinero que tengo en el banco es : {0:C}",dinero);

Ese :C de más quiere decir que formatearemos la entrada como una moneda, por ejemplo en el caso del peso Colombiano, yen japonés, el euro alemán o el peso mexicano. La C determina el tipo de formato, y la cultura, la forma de llevarlo a cabo.

Otros ejemplos son: D para decimal, E para notación exponencial o científica, F para punto decimal fijo (i.e. 4 => 4.0), G para la versión general, es decir, la más compacta posible; N para un número con separador de miles, decimales, etc.; P para porcentaje, R para redondear, X para hexadecimal.

 s = string.Format("{0:D}", 99901); // s == 99901
s = string.Format("{0:D10}", 99901); // s == 0000099901
s = string.Format("{0:E}", 1983.42"); // s == 1.98342E+003
s = string.Format("{0:F2}", 1983"); // s == 1983.00
s = string.Format("{0:F3}", 1983.4266"); // s == 1983.427
s = string.Format(japones, "{0:N}", 1983.55); // s == 1.983,55
s = string.Format("{0:P}", 0.42); // s == 42 %
s = string.Format("{0:X4}", 255); // s == 00FF
Si ninguna de estas nos satisface, podemos crear nuestro propio formato mediante el formato de números especializado. Para hacer esto, podemos colocar en lugar del D, E, C, etc., un 0 para representar un dígito, si existe, o un cero si no; un # para representar un dígito si existe, si no, no muestra nada; El punto . para separar decimales y la coma para separar grupos. Asimismo, tenemos % para porcentaje, ‰ para por-miles, E0 para notación exponencial, ‘cadena’ para poner una cadena de texto fija.

 s = string.Format("{0:0,00.00#:D}", 99.1); // s == 0,99.10
s = string.Format(aleman, "{0:0,00.00#:D}", 99.1); // s == 0.99,10
s = string.Format("{0:000,000.000}", 9991); // s == 009,991.000
s = string.Format("{0:#,#00}", 99.1); // s == 99
s = string.Format("{0:#,#00}", 9.1); // s == 09
s = string.Format("{0:#,#00}", 9999.1); // s == 9,999
s = string.Format("{0:##-###-##}", 99942); // s == 999-42
s = string.Format("{0:##-###-##}", 4299942); // s == 42-999-42
El formato también podemos aplicarlo a las fechas, de forma muy similar a como se aplica para números. Existen muchos formatos, pero los más utilizados son los siguientes: se usa la d y D para una fecha corta y una fecha larga, respectivamente; f y F para fecha con tiempo corto y largo, u y U para formato universal corto y largo.

 CultureInfo enUS = new CultureInfo("en-US");
CultureInfo deDE = new CultureInfo("de-DE");
CultureInfo esMX = new CultureInfo("es-MX");

DateTime tm = new DateTime(2012, 12, 04, 11, 05, 42);
s = string.Format(esMX, "{0:d}", tm); // s == 12/04/2012
s = string.Format(esMX, "{0:d}", tm); // s == 04/12/2012
s = string.Format(deDE, "{0:D}", tm); // s == Dienstag, 4. Dezember 2012
s = string.Format(enUS, "{0:f}", tm); // s == Tuesday, 4 Dic, 2012 11:05
Etcétera. También podemos utilizar formato especial usando y, M, d, m, h, M, s para representar año, mes, día, minuto hora, segundo, etc. Por ejemplo, cuatro yes suponen año en formato de cuatro dígitos, como 1983. Dos yes y tendríamos 83.

 s = string.Format(esMX, "{0:ddd d MMM}", tm);
// s == mar 4 dic
s = string.Format(esMX, "{0:dddd d MMMM}", tm);
// s == martes 4 diciembre
s = string.Format(esMX, "{0:H mm ss}", tm);
// s == 11 05 42
s = string.Format(esMX, "{0:y yy yyyy yyyyy}", tm);
// s == 2 12 2012 02012

jueves, 21 de marzo de 2013

Conceptos de C#

Enumerables

Son clases que implementan las interfaces:
IEnumerable: Que premitira enumerar sus propiedades.
IEnumerator: El que retornara las propiedades

por ejemplo: IList, Dictionary


BITARRAY

Esta clase, ubicada en el espacio de nombres System.Collections.
  • Implementa ICollection.
  • No permite agregar elementos luego de creado.
  • El tamaño se define en el constructor. 
Ejemplos:
BitArray bits1 = new BitArray(10);
BitArray bits2 = new BitArray(bits1);
boo[] boolArray = new bool[] { true, true, false, true, false, false, false };
BitArray bits3 = new BitArray(boolArray);
BitArray bits4 = new BitArray(10, true);
byte[] byteArray = new byte[] { 0xff, 0x00 };
BitArray bits5 = new BitArray(byteArray);

La primera llamada nos genera un array con diez bits. La segunda llamada nos genera un array el cual copia el tamaño y los bits contenidos en el primer array. El tercer arreglo se crea con siete bits de la forma 1101000, y la siguiente llamada nos genera un arreglo de diez bits, todos inicializados a 1. Finalmente, la quinta llamada nos genera un array de 16 bits, con los primeros ocho bits establecidos a 1 y los siguientes ocho establecidos a 0. 


COLECCIONES PARA TRABAJAR CON TEXTO

en este apunte vamos a explorar algunas de las clases que podemos utilizar, en particular, para trabajar con cadenas de texto: StringCollection, StringDictionary y NameValueCollection.
Todas están dentro del espacio de nombres System.Collections.Specialized.

StringCollection: ésta representa una colección de cadenas de texto:
  • Está particularmente optimizada para trabajar con cadenas de texto.
  • La colección cuenta con varias propiedades estándares, como SyncRoot e IsSynchronized para temas de concurrencia y sincronización en el acceso a elementos;
  • Count: Obtiene el número de la colección.
  • IsReadOnly: Saber si se puede agregar elementos a la colección.
  • Indexador para obtener una cadena de acuerdo al indicado.
  • Métodos Add, Remove, Insert.
  • AddRange para agregar un array de cadenas de una vez.


StringDictionary: implementa un Hashtable pero fuertemente tipado para emplear cadenas de texto.



NameValueCollection: se comporta como StringDictionary, pero es una colección no un diccionario.

  • Nos permite acceder a los elementos via indice y clave.
  • Nos permite en el constructor especificar el comparador.

Esto es una resumida explicación del trabajo con estas colecciones.
Fuente


TRES DICCIONARIOS ESPECIALIZADOS

  • ListDictionary: mientras Hashtable almacena los pares llave-valor en bloques de memoria que son accesibles vía el código hash de la llave, ListDictionary los almacena como si fuera una lista enlazada. Es decir, el primer elemento contiene el par llave-valor, más un apuntador (o referencia, en el argot de C#) al elemento siguiente, y así sucesivamente hasta llegar al final de la lista. Esto implica que ListDictionary no manipula la memoria (o al menos, no de la forma en que Hashtable lo hace) y por lo tanto el acceso a los elementos es más eficiente en términos de memoria y procesamiento. Esto quiere decir que si la lista es pequeña, el rendimiento es bueno con ListDictionary mientras que si la lista es de un tamaño grande, entonces es mejor trabajar con HashTable.


  • HybridDictionary: Supongamos que tenemos un escenario en el cual tenemos un diccionario que generalmente tiene pocos elementos. Pero que bajo ciertas circunstancias, éste puede crecer. Para no perder el rendimiento, tendríamos que usar ListDictionary y cuando éste crezca, copiar todos los elementos a un Hashtable. Pues bien, hay una colección que hace precísamente eso: HybridDictionary. Esta clase emplea de forma interna un ListDictionary cuando el número de elementos se mantiene bajo, pero que cambia a Hashtable cuando el número crece.



OrderedDictionary: Es un diccionario que mantiene ordenados los elementos basados en la llave de los mismos en bloques de memoria contigua, de forma muy similar a como los almacena un array o un vector. La principal ventaja de esto es que podemos acceder a los elementos no solamente a través de la llave, sino también a través de un índice.


Y esos son los tres diccionarios especializados, aunque existen mas, pero luego hablaremos de ellos.
                                                                                                                                                          Fuente


COLLECTIONBASE, READONLYCOLLECTIONBASE Y DICTIONARYBASE

CollectionBase: Clase que sirve de base para crear colecciones.
  • Implementa estas tres interfaces: IList, ICollection e IEnumerable.
ReadOnlyCollectionBase: La finalidad es que podamos crear colecciones de solo lectura, es decir, que no podamos agregar o eliminar elementos, solo leerlos.
DictionaryBase: También existe una clase análoga a CollectionBase, solo que para diccionarios: DictionaryBase. La clase está estructurada de forma similar a su contraparte. Existen los miembros Count, Clear, CopyTo y GetEnumerator como públicos, así como los métodos para realizar validaciones(OnClear, OnInsert, OnGet, OnSet, OnRemove, OnValidate, etc.) solo que acomodados para poder recibir pares llave-valor. La diferencia más grande (aparte de que esta clase implementa IDictionary en lugar de IList) es que esta clase tiene dos propiedades públicas, Dictionary (de tipo IDictionary) e InnerHashtable (de tipo Hashtable), contrapertes de List e InnerList respectivamente. Ambas representan el diccionario subyacente de DictionaryBase.

COLLECTION GENERIC

Como habrás podido imaginar, el proceso de envolver/desenvolver tipos valor es un proceso que consume recursos, y de hecho hacer esto seguido puede causar daños en rendimiento a tu programa. Comprenderás ahora el problema de utilizar ArrayList (o cualquier colección de las que hemos visto) con tipos de dato valor. Y esto es algo que ni siquiera se soluciona heredando de CollectionBase/DictionaryBase. La única forma real de solventar esta situación sería crear una clase que implemente ICollection/IList/IDictionary y utilizar arrays, los cuales tendríamos que redimensionar manualmente. Y esto no es particularmente productivo.

La llegada de los genéricos en .NET 2.0 solucionó este problema. El poder usar genéricos nos evita los boxings y unboxings para las estructuras, y naturalmente, proporciona métodos y clases fuertemente tipadas. Podríamos reescribir el método foo de hace tres párrafos de la siguiente forma.
A partir de .NET 2.0 se crearon muchas clases de colecciones genéricas, la mayoría bajo el espacio de nombres System.Collections.Generic.
INTERFACES
  • IEnumerable<T>
  • ICollection<T>
  • IList<T>
  • IDictionary<K,V>
CLASES
  • Queue<T>
  • Stack<T>
  • SortedList<T>
  • SortedDictionary<K,V>: Mantiene el diccionario ordenado por la llave
  • LinkedList<T>: Un ejemplo de esta clase:
LinkedList<string> list = new LinkedList<string>();
list.AddLast("Seiya");
list.AddLast("Shiriu");
list.AddLast("Yoga");
list.AddLast("Shun");
list.AddLast("Ikki");

     for (LinkedListNode<string> node = list.First; node != null; node = node.Next)
      {
            string prev = node.Previous != null ? node.Previous.Value : "NULL";
              string next = node.Next != null ? node.Next.Value : "NULL";
                Console.WriteLine("[{0}] - {1} - [{2}]", prev, node.Value, next);
            }
            • List<T>: Todo sobre esta clase la podemos encontrar en el siguiente link
            CLASES
            CODIGO SNIPPETS
            Esta es la ruta donde se encuentran los archivos de los códigos Snippets:
            C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC#\Snippets\1033\Visual C#

            Un ejemplo de un archivo, es el siguiente:
            Nombre Archivo: query.snippet
            Contenido:

            <?xml version="1.0" encoding="utf-8"?>
            <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2008/CodeSnippet">
              <CodeSnippet Format="1.0.0">
                <Header>
                  <Title>query</Title>
                  <Shortcut>query</Shortcut>
                  <Description>Genera un método encapsulado para consultar datos en la base de datos</Description>
                  <Author>Sensei - Servinte</Author>
                  <SnippetTypes>
                    <SnippetType>Expansion</SnippetType>
                    <SnippetType>SurroundsWith</SnippetType>
                  </SnippetTypes>
                </Header>
                <Snippet>
                  <Declarations>
                    <Literal>
                      <ID>type</ID>
                      <ToolTip>método de consulta de datos</ToolTip>
                      <Default>object</Default>
                    </Literal>
                  </Declarations>
                  <Code Language="CSharp">
                    <![CDATA[
                    /// <summary>
                    ///
                    /// </summary>       
                    public static $type$ nameMethod()
                    {
                        return GetExistMC();
                    }
                    /// <summary>
                    ///
                    /// </summary>       
                    static $type$ GetNameMethod()
                    {
                        const string methodName = "GetOrderReportHandler::GetNameMethod()";
                        bool result = false;
                        ParameterValues parameters = new ParameterValues();
                       
                        try
                        {
                            BaseRuntime.Trace("chhhcecli", methodName, "Inicia:  descripcion de lo que hace el método");
                            string query = ResourceHelper.GetQuery(Servinte.Clinic.Orders.Reads.Resources.Resources.Queries, BaseRuntime.ProviderName, "ID_QUERY");              
                            parameters.Add(secuence, DbType.Int32);

                            using (DatabaseManager db = new DatabaseManager(BaseRuntime.ProviderEnum, BaseRuntime.ConnectionString))           
                            using (IDataReader reader = db.ExecuteReader(query,parameters,null))
                            {
                                while (reader.Read())
                                {
                                    if (!reader.IsDBNull(0))
                                    {
                                       
                                    }
                                }
                                if (reader.IsClosed)
                                    reader.Close();
                            }
                        }
                        catch (Exception ex)
                        {
                            BaseRuntime.Log("chhhcecli", methodName, ex);
                            throw ex;
                        }
                        finally
                        {
                            BaseRuntime.Trace("chhhcecli", methodName, "Fin:  Descripción de lo que hizo el método");
                        }
                        return result;
                    }]]>
                  </Code>
                </Snippet>
              </CodeSnippet>
            </CodeSnippets>

            lunes, 11 de marzo de 2013

            miércoles, 6 de marzo de 2013

            Merge en CSharp

            Se me presento un problema al realizar el Merge de dos tablas, pues llegaba un momento en el cual los nuevos datos que queria agregar a la tabla principal, de la tabla nueva, me duplicaba las columnas. Esto me complicaba luego cuando queria trabajar con los datos de la tabla, pues al tener columnas duplicadas ya se imaginaran que sucederia.
            La solución fue especificarle los siguientes parámetros:
            dtPrincipal.Merge(dtSecundaria,true,MissingSchemaAction.Ignore);

            dtPrincipal = DataTable principal donde estamos almacenando la información.
            dtSecundaria = DataTable secundaria donde tenemos los datos

            miércoles, 27 de febrero de 2013

            Ventana Popup En Control WPF

            Para asignar una ventana popup a un control, se puede realizar la siguiente lógica. En nuestro ejemplo vamos a mostrar una ventana popup para un boton, osea al dar clic en el botón se mostrara  la ventana.
            El código para mostrar la ventana se agrega en el evento clic del botón:


            private void Boton_Click(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
                    {
                        try
                        {
                            Dictionary<string, string> paramUserControl = new Dictionary<string, string>();
                            paramUserControl.Add("unParametro");

                            //Instanciamos el control wpf que va a mostrar la información.
                            UCExample u = new UCExample ();
                            u.SetContext(paramStateTreatment);

                            //Instanciamos la ventana contenedora del control
                            Popup popup = new Popup()
                            {
                                Child = u,
                                AllowsTransparency = true,
                                StaysOpen = true,
                                IsOpen = false,
                                PlacementTarget = ((System.Windows.Controls.Control)(e.OriginalSource)),
                                Placement = PlacementMode.Left
                            };

                            //Binding para setear la propiedad "Width" del contenedor con la ventana de la información
                            Binding widthBinding = new Binding("Width") { Mode = BindingMode.OneWay, Source = popup };
                            ((FrameworkElement)u).SetBinding(WidthProperty, widthBinding);

                             //Le damos un tiempo para mostrar la ventana
                            DispatcherTimer activeTimer = new DispatcherTimer { Interval = new TimeSpan(0,0,7) };
                            activeTimer.Tick += (obj, ea) => ClosePopup(popup);
                            activeTimer.Start();

                            popup.IsOpen = true;
                            return;
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }

            Dentro de una ventana popup puede ir cualquier template. El código del usercontrol que va a ir dentro de la ventana popup, es el siguiente:

            XAML

            <UserControl x:Class="Servinte.Clinic.Controls.UCSeeTreatmentStatus"
                         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                         mc:Ignorable="d" Height="Auto" Width="Auto">
                <UserControl.Resources>
                    <Style TargetType="Label" x:Key="lblControl">
                        <Setter Property="HorizontalContentAlignment" Value="Left"/>
                    </Style>
                    <Style TargetType="TextBlock" x:Key="txtbControl">
                        <Setter Property="HorizontalAlignment" Value="Left"/>
                        <Setter Property="VerticalAlignment" Value="Center"/>
                    </Style>
                </UserControl.Resources>
                <Border Background="White" BorderBrush="Black" BorderThickness="2">
                    <Grid Margin="5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Label Content="Nombre " Style="{StaticResource lblControl}"/>
                        <TextBlock Grid.Column="1" Name="txtbName" Style="{StaticResource txtbControl}"/>
                        <Label Grid.Row="1" Content="Apellidos " Style="{StaticResource lblControl}"/>
                        <TextBlock Grid.Row="1" Grid.Column="1" Name="txtbLastName" Style="{StaticResource txtbControl}"/>
                        <Label Grid.Row="2" Content="Profesión " Style="{StaticResource lblControl}"/>
                        <TextBlock Grid.Row="2" Grid.Column="1" Name="txtbProfession" Style="{StaticResource txtbControl}"/>
                        <Label Grid.Row="3" Content="Fecha Nacimiento " Style="{StaticResource lblControl}"/>
                        <TextBlock Grid.Row="3" Grid.Column="1" Name="txtbDateBorn" Style="{StaticResource txtbControl}"/>
                    </Grid>
                </Border>
            </UserControl>


            C#

            using System.Collections.Generic;
            using System.Windows.Controls;

            namespace MyNamespace.Controls
            {
                /// <summary>
                /// Interaction logic for UCExample.xaml
                /// </summary>
                public partial class UCExample : UserControl
                {
                    public UCExample()
                    {
                        InitializeComponent();
                    }

                    /// <summary>
                    /// Seteamos el contexto de la ventana que informa los datos de la persona
                    /// </summary>
                    public void SetContext(Dictionary<string,string> param)
                    {           
                        //Nombre
                        txtbName.Text = string.Format(": {0}", param["Name"]);
                        //Apellidos
                        txtbLastName.Text = string.Format(": {0}", param["LastName"]);
                        //Profesion
                        txtbProfession.Text = string.Format(": {0}", param["Profesion"]);
                        //Fecha de nacimiento
                        txtbDateBorn.Text = string.Format(": {0}",param["DateBorn"]));           
                    }
                }
            }