1

我的World班级有一个如下所示的属性:

    public Vec2 Gravity
    {
        get {
            Console.WriteLine("Getting gravity!");
            return GetGravity(); 
        }
        set {
            Console.WriteLine("Setting gravity!");
            SetGravity(value); 
        }
    }

“获得重力!” 当尝试读取该值时,字符串按预期显示PropertyGrid,但是当我尝试更改重力矢量并按 Enter 时,没有任何反应。为什么不?


我的Vec2班级有以下属性:

    public float X
    {
        get
        {
            return x;
        }
        set
        {
            x = value;
        }
    }

    public float Y
    {
        get
        {
            return y;
        }
        set
        {
            y = value;
        }
    }

由于以下原因,它们在网格上可见:

public class Vec2Converter : ExpandableObjectConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
    {
        if (destinationType == typeof(Vec2)) return true;
        else return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType)
    {
        if (destinationType == typeof(string) && value is Vec2)
        {
            Vec2 vec = (Vec2)value;
            return string.Format("{0}, {1}", vec.X, vec.Y);
        }
        else return base.ConvertTo(context, culture, value, destinationType);
    }
}

我刚刚将这两种方法添加到了Vec2Converter,现在它可以工作了:

    public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
    {
        if (sourceType == typeof(string)) return true;
        else return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            try
            {
                string strVal = value as string;
                var parts = strVal.Split(',');
                float x = float.Parse(parts[0]);
                float y = float.Parse(parts[1]);
                return new Vec2(x, y);
            }
            catch
            {
                throw new ArgumentException("Can not convert '" + (string)value + "'to type Vec2");
            }
        }
        else return base.ConvertFrom(context, culture, value);
    }

它通过更改字符串表示和单个属性来工作。为什么 thix 会针对具有单个属性的情况修复它?


认为答案Vec2结构,所以当返回World向量时Gravity,它按值传递它,然后更改副本,而不是实际的Gravity向量。

我认为解决方案是保留CanConvertFromandConvertFrom方法。我假设它们使它起作用,因为它们修改了重力向量的字符串表示,然后更新了实际的重力向量。那个,或者创建Vec2一个类应该可以工作,但是我现在不能真正测试它,因为我的应用程序非常依赖它是一个结构。

4

5 回答 5

1

我认为属性网格是直接在 Vec2 对象上设置属性(即XY属性)。

于 2010-01-18T00:30:07.687 回答
1

它正在更改 的 X 和 Y 属性Vec2,因为这就是您要设置的。在更改这些属性时,如果将其转换为代码,我猜它正在调用Gravity.X = value;,当您考虑时,它实际上是一个Geton Gravity,然后是一个Seton Vec2.X

使用您当前的代码,为了输入Setof Gravity,您需要将其显式更改为新Vec2对象。

编辑:显然, [NotifyParentProperty(true)]没有好处,清除我的不确定性。

于 2010-01-18T01:06:45.630 回答
1

这是 PropertyDescriptorGridEntry.SetPropertyValueCore 的代码:

protected void SetPropertyValueCore(object obj, object value, bool doUndo)
{
    if (this.propertyInfo != null)
    {
        Cursor current = Cursor.Current;
        try
        {
            Cursor.Current = Cursors.WaitCursor;
            object component = obj;
            if (component is ICustomTypeDescriptor)
            {
                component = ((ICustomTypeDescriptor) component).GetPropertyOwner(this.propertyInfo);
            }
            bool flag = false;
            if (this.ParentGridEntry != null)
            {
                Type propertyType = this.ParentGridEntry.PropertyType;
                flag = propertyType.IsValueType || propertyType.IsArray;
            }
            if (component != null)
            {
                this.propertyInfo.SetValue(component, value);
                if (flag)
                {
                    GridEntry parentGridEntry = this.ParentGridEntry;
                    if ((parentGridEntry != null) && parentGridEntry.IsValueEditable)
                    {
                        parentGridEntry.PropertyValue = obj;
                    }
                }
            }
        }
        finally
        {
            Cursor.Current = current;
        }
    }
}

在您的情况下, Vec2 是一种值类型,因此 flag 为真。在网格中, vec2 实例是您的结构的副本,因此您的原始实例尚未修改,但当 parentGridEntry.PropertyValue = obj; 被调用,然后通过容器类中 Gravity 属性的 PropertyDescriptor 分配值。您添加 CanConvertFrom 的事实指示网格 parentGridEntry.IsValueEditable 现在为真。

于 2010-01-18T01:25:51.537 回答
0

答案取决于您如何编辑属性:

如果您通过直接在属性中输入文本来编辑属性,Gravity那么我怀疑您TypeConverter将被调用并且Gravity应该调用属性的设置器。这是假设 Gravity 属性甚至在属性网格中显示为可编辑的,我怀疑它应该如此。

如果您通过展开属性(单击小+符号)来编辑属性,然后直接设置其XY属性,则Gravity永远不会调用该属性的设置器。只有XandY属性才会调用它们的设置器。

一般来说,在大多数框架中,复杂的属性是不可设置的。它们通常仅通过其子属性设置。在这种情况下,我认为让整个属性可设置是合理的,因为这似乎是一种常见的操作。这只是一种设计选择,无论哪种方式都没有对错。

于 2010-01-18T00:29:24.080 回答
0

在托管 C++ 中:

[TypeConverter(ExpandableObjectConverter::typeid)]  
public ref struct Vector3
{
    float x, y, z;   

    property float X   
    {   
        float get()             { return x; }
        void set(float value)   { x = value; }
    }   
    property float Y   
    {   
        float get()             { return y; }
        void set(float value)   { y = value; }
    }   
    property float Z
    {   
        float get()             { return z; }
        void set(float value)   { z = value; }
    }
};
于 2010-11-02T17:01:19.277 回答