【问题标题】:Conversion error in a property in PropertyGridPropertyGrid 中的属性转换错误
【发布时间】:2014-03-11 01:22:54
【问题描述】:

我编写了一个 C# Winforms 应用程序。其中一种形式允许通过 PropertyGrid 控件进行配置。我已经为一个属性编写了 TypeConverters,它是一个可以完美运行的对象,但有点细节。

该属性显示一个标准值集合,其元素为 Simbologia 类型。目标属性的类型为 CodigoBarra。

过程如下:当values集合中的第一个元素被选中时,属性赋值为null,不显示对象属性。当在集合中选择不同的值时,CodigoBarra 属性会展开,允许单独更改对象属性。

正如我所说,所有这些过程都有效,但是,当我将集合设置为独占时,就会出现问题。当我按键时,系统无法从 Simbologia 转换为 CodigoBarra。

我尝试过使用 ConvertFrom 方法,甚至向 Simbologia 类添加了隐式转换,但没有帮助。

我使用 Propertygrid 配置的对象称为 Equipo,这是定义:

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;
    }
}

我只留下了 CodigoBarra 财产。

BarCodeConverter如下:

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);
    }
}

正如您在 GetStandardValues 方法中看到的,该集合是使用 Configuracion.Simbologia.GetValues() 调用构建的,该调用返回一个 Simbologia 对象数组。

很明显会产生不匹配,但是为什么只有在按键时才会产生错误?当我使用下拉列表选择 Simbologia 对象时,它可以工作。

最后,这是我在 Simbologia 类中实现的隐式转换:

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

我该如何解决?

任何帮助将不胜感激。

谢谢 詹姆

【问题讨论】:

  • “将收藏设置为独占”是什么意思?你有完整的重现代码吗?
  • 与.NET的含义相同。看方法:GetStandardValuesExclusive

标签: winforms c#-4.0 type-conversion propertygrid typeconverter


【解决方案1】:

最后,我用这个类型转换器解决了它:

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);
        }
    }

这是符号类:

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;
        }

最后,这是 CodigoBarra 类:

[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();
    }
}

问候, 詹姆

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    相关资源
    最近更新 更多