6
votes

Modification de la propriété de structure dans une propriétéGrade

pourquoi someclass.classfield.tructfield code> Propriété ne change pas dans un PropertyGrid code>? Il semble que PropertyGrid code> n'appelle pas someclass.classfield.set code> après sinistress code> instance a été modifié. Mais le même code fonctionne bien avec point code> au lieu de somestract code>.

[TypeConverter(typeof(ExpandableObjectConverter))]
public struct SomeStruct
{
    private int structField;

    public int StructField
    {
        get
        {
            return structField;
        }
        set
        {
            structField = value;
        }
    }

    public override string ToString()
    {
        return "StructField: " + StructField;
    }
}

[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class SomeClass
{
    public SomeStruct ClassField
    {
        get;
        set;
    }
}

...

var someClass = new SomeClass
{
    ClassField = new SomeStruct
    {
        StructField = 42
    }
};
propertyGrid.SelectedObject = someClass;


5 commentaires

Les structures sont censées être immuables


Celui-ci est mutable. Même chose que point / rectangle / etc.


Bon point (caractères supplémentaires)


Notez le mot "objet" dans "expanstableObjectConverter". Vous allez modifier une copie en boîte de la structure, elle ne se propage pas. Utilisez la mise en œuvre de PointConverter à titre d'exemple.


@Hans Passant, merci beaucoup, ça marche.


3 Réponses :


8
votes

Vous avez besoin d'un type de typonverter spécial qui remplace tyconverter.gecreateInstancesupported car sinon La magie Copy-By-Value / Boxing se produit derrière la scène de la manière dont la grille de propriété gère tout cela.

Voici un élément qui devrait fonctionner pour la plupart des types de valeur. Vous le déclarez comme ceci: p>

[TypeConverter(typeof(ValueTypeTypeConverter<SomeStruct>))]
public struct SomeStruct
{
    public int StructField { get; set; }
}


public class ValueTypeTypeConverter<T> : ExpandableObjectConverter where T : struct
{
    public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
    {
        if (propertyValues == null)
            throw new ArgumentNullException("propertyValues");

        T ret = default(T);
        object boxed = ret;
        foreach (DictionaryEntry entry in propertyValues)
        {
            PropertyInfo pi = ret.GetType().GetProperty(entry.Key.ToString());
            if (pi != null && pi.CanWrite)
            {
                pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null);
            }
        }
        return (T)boxed;
    }
}


0 commentaires

3
votes

J'ai modifié la réponse de Simon Mourier pour éviter que le besoin d'appréciation d'appréciation est un générique: xxx


0 commentaires

0
votes

Dans mon cas, l'argument générique n'est pas connu au moment de la compilation (structure d'options pour un plugin). Vous pouvez obtenir une copie de la valeur actuelle à l'aide de context.propertydescriptor.getvalue (context.Instance); : xxx


0 commentaires