Вопрос

I programmed a C# Winforms application. One of the forms allow to configure something, by mean of a PropertyGrid control. I have programmed TypeConverters for a property that is an object that works perfectly, but a little detail.

The property shows a stardard value collection, whose elements are of type Simbologia. The target property is of type CodigoBarra.

The process is as follows: when the first element in the values collection is selected, the property assigns null and no object properties are displayed. When a different value is selected in the collection, the CodigoBarra properties expand, allowing to change the object properties individually.

As I told, all that process work, however, the problem occurs when I set the collection as exclusive. When I press a key, the system is not able to convert from Simbologia to CodigoBarra.

I have tried with ConvertFrom methods, and even, I added an implicit cast to Simbologia class, but it did not help.

The object I am configuring with the Propertygrid is called Equipo, and this is the definition:

public class Equipo : IConfiguracion
{
    [Category("Impresora"),
     DefaultValue(null),
     PropertyOrder(16),
     TypeConverter(typeof(PropertyGrid.BarCodeConverter)),
     DisplayName("Código de Barras"),
     Description("Definición del código de barra cuando se imprime el ticket. El código aparecerá a continuación del texto.")]
    public CodigoBarra CodigoBarra { get; set; }

    public Equipo()
    {
        this.NombreBiometrico = this.NombreImpresora = String.Empty;
        this.PuertoBiometrico = 4370;
        this.IpImpresora = "0.0.0.0";
        this.PuertoImpresora = 0;
        this.AutoCorte = true;
        this.ImprimeTicket = true;
    }

    public Equipo(string ipBiometrico) 
        : this()
    {
        this.ID = 0;
        this.IpBiometrico = ipBiometrico;
        this.Nuevo = true;
    }

    public Equipo(string nombreBiometrico, string ipBiometrico)
        : this()
    {
        this.ID = 0;
        this.NombreBiometrico = nombreBiometrico;
        this.IpBiometrico = ipBiometrico;
        this.Nuevo = true;
    }

    public Equipo(int id, string ipBiometrico) 
        : this()
    {
        this.ID = id;
        this.IpBiometrico = ipBiometrico;
        this.Nuevo = id == 0;
    }

    public Equipo(int id, string nombreBiometrico, string ipBiometrico)
        : this()
    {
        this.ID = id;
        this.NombreBiometrico = nombreBiometrico;
        this.IpBiometrico = ipBiometrico;
        this.Nuevo = id == 0;
    }
}

I have left only CodigoBarra property.

BarCodeConverter is as follows:

public class BarCodeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || sourceType == typeof(MonitorView.Configuracion.Simbologia) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        string stringValue = value as string;
        object result = null;

        if (!string.IsNullOrEmpty(stringValue))
        {
            var valor = new Configuracion.Simbologia(stringValue);

            if (valor.Codigo != InDriver.BarCodeInfo.SymbologyDef.None)
                result = new MonitorView.Configuracion.CodigoBarra(valor);
        }

        return result;
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        MonitorView.Configuracion.CodigoBarra codigoBarra = value as MonitorView.Configuracion.CodigoBarra;

        object result = null;

        if (codigoBarra == null)
        {
            if (value != null)
            {
                Configuracion.Simbologia simbologia = value as Configuracion.Simbologia;

                if (destinationType == typeof(string) && !Configuracion.Simbologia.IsNone(simbologia))
                    result = simbologia.ToString();
            }
        }
        else
        {
            if (destinationType == typeof(string) && !Configuracion.Simbologia.IsNone(codigoBarra.Symbology))
                result = codigoBarra.ToString();
        }

        if (String.IsNullOrEmpty((string)result))
            result = "[ ninguno ]";

        return result ?? base.ConvertTo(context, culture, value, destinationType);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        return true;
    }

    public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(Configuracion.Simbologia.GetValues());
    }

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        return TypeDescriptor.GetProperties(value, attributes);
    }
}

As you see in GetStandardValues method, the collection is built with Configuracion.Simbologia.GetValues() call, which returns an array of Simbologia objects.

It is obvious that the mismatch will be produced but, why the error is produced only when I press a key? When I select the Simbologia object using the dropdownlist, it works.

Finally, this is the implicit cast I implemented in Simbologia class:

public static implicit operator CodigoBarra(Simbologia simbologia)
{
    return new CodigoBarra(simbologia);
}

How can I solve it?

Any help will be greatly appreciated.

Thanks Jaime

Это было полезно?

Решение

Finally, I have solved it using this type converter:

public class BarCodeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || sourceType == typeof(MonitorView.Configuracion.Simbologia) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            string stringValue = value as string;
            object result = null;

            if (!string.IsNullOrEmpty(stringValue))
            {
                var valor = new Configuracion.Simbologia(stringValue);

                if (valor.Codigo != InDriver.BarCodeInfo.SymbologyDef.None)
                    result = new MonitorView.Configuracion.CodigoBarra(valor);
            }

            return result;
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            MonitorView.Configuracion.CodigoBarra codigoBarra = value as MonitorView.Configuracion.CodigoBarra;

            object result = null;

            if (codigoBarra == null)
            {
                if (value != null)
                {
                    Configuracion.Simbologia simbologia = value as Configuracion.Simbologia;

                    if (destinationType == typeof(string) && !Configuracion.Simbologia.IsNone(simbologia))
                        result = simbologia.ToString();
                }
            }
            else
            {
                if (destinationType == typeof(string) && !Configuracion.Simbologia.IsNone(codigoBarra.Symbology))
                    result = codigoBarra.ToString();
            }

            if (String.IsNullOrEmpty((string)result))
                result = "[ ninguno ]";

            return result ?? base.ConvertTo(context, culture, value, destinationType);
        }

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true;
        }

        public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            return new StandardValuesCollection(Configuracion.Simbologia.GetValues());
        }

        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            return TypeDescriptor.GetProperties(value, attributes);
        }
    }

This is Symbologia class:

public class Simbologia
    {
        public InDriver.BarCodeInfo.SymbologyDef Codigo { get; set; }

        public Simbologia(InDriver.BarCodeInfo.SymbologyDef codigo)
        {
            this.Codigo = codigo;
        }

        public Simbologia(string nombreCodigo)
        {
            this.Codigo = Enum.GetValues(typeof(InDriver.BarCodeInfo.SymbologyDef)).Cast<InDriver.BarCodeInfo.SymbologyDef>().Where(s => s.ToString() == nombreCodigo).FirstOrDefault();
        }

        public static implicit operator CodigoBarra(Simbologia simbologia)
        {
            return new CodigoBarra(simbologia);
        }

        public override string ToString()
        {
            return this.Codigo.ToString();
        }

        public static Array GetValues(params object[] excludes)
        {
            var valores = Enum.GetValues(typeof(InDriver.BarCodeInfo.SymbologyDef)).Cast<InDriver.BarCodeInfo.SymbologyDef>();

            List<Simbologia> simbologias = new List<Simbologia>(valores.Count());
            foreach (var valor in valores)
                if (excludes.Count() == 0 || excludes.FirstOrDefault(e => e.ToString() == valor.ToString()) == null)
                    simbologias.Add(new Simbologia(valor));

            return simbologias.ToArray();
        }

        public static bool IsNone(Simbologia simbologia)
        {
            return simbologia == null || simbologia.Codigo == InDriver.BarCodeInfo.SymbologyDef.None;
        }

And finally, this is CodigoBarra class:

[TypeConverter(typeof(PropertySorter))]
public class CodigoBarra
{
    [DefaultValue(70),
     PropertyOrder(1),
     TypeConverter(typeof(StringConverter)),
     DisplayName("Alto"),
     Description("Alto del código de barras, en puntos (depende de la impresora).")]
    public byte Height { get; set; }

    [DefaultValue(2),
     PropertyOrder(2),
     TypeConverter(typeof(StringConverter)),
     DisplayName("Ancho"),
     Description("Ancho del código de barras, en puntos (depende de la impresora).")]
    public byte Width { get; set; }

    [DefaultValue(0),
     PropertyOrder(3),
     TypeConverter(typeof(StringConverter)),
     DisplayName("Alineamiento"),
     Description("Distancia desde el borde izquierdo del código de barras, en puntos (depende de la impresora).")]
    public byte Alignment { get; set; }

    [DefaultValue(InDriver.BarCodeInfo.TextPositionDef.None),
     PropertyOrder(4),
     DisplayName("Posición del Texto"),
     Description("Posición del texto con respecto al código de barras.")]
    public InDriver.BarCodeInfo.TextPositionDef TextPosition { get; set; }

    [DefaultValue(null),
     PropertyOrder(5),
     DisplayName("Simbología"),
     TypeConverter(typeof(PropertyGrid.SymbologyConverter)),
     Description("Tipo de simbología con la cual se codifica el código de barra. No todas las impresoras soportan las mismas simbologías.")]
    public Simbologia Symbology { get; set; }

    public CodigoBarra()
    {
        this.Symbology = null;
        this.Alignment = 0;
        this.Height = 70;
        this.Width = 2;
        this.TextPosition = InDriver.BarCodeInfo.TextPositionDef.None;
    }

    public CodigoBarra(Simbologia symbology, byte alignment, byte height, byte width, InDriver.BarCodeInfo.TextPositionDef textPosition)
    {
        this.Symbology = symbology;
        this.Alignment = alignment;
        this.Height = height;
        this.Width = width;
        this.TextPosition = textPosition;
    }

    public CodigoBarra(Simbologia symbology)
        : this()
    {
        this.Symbology = symbology;
    }

    public CodigoBarra(InDriver.BarCodeInfo info)
        : this()
    {
        SetBarCodeInfo(info);
    }

    public CodigoBarra(string info)
        : this()
    {
        SetBarCodeInfo(InDriver.BarCodeInfo.GetInformation(info));
    }

    public InDriver.BarCodeInfo GetBarCodeInfo()
    {
        InDriver.BarCodeInfo info = new InDriver.BarCodeInfo();
        info.Symbology = this.Symbology == null ? InDriver.BarCodeInfo.SymbologyDef.None : this.Symbology.Codigo;
        info.Height = this.Height;
        info.Width = this.Width;
        info.Alignment = this.Alignment;
        info.TextPosition = this.TextPosition;

        return info;
    }

    public void SetBarCodeInfo(InDriver.BarCodeInfo info)
    {
        if (info != null)
        {
            this.Symbology = new Simbologia(info.Symbology);
            this.Height = info.Height;
            this.Width = info.Width;
            this.Alignment = info.Alignment;
            this.TextPosition = info.TextPosition;
        }
    }

    public override string ToString()
    {
        return this.Symbology.ToString();
    }
}

Regards, Jaime

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top