tags:

views:

203

answers:

1

I have a canvas that I can create and drop elements onto. I can move them and size them with a thumb or through binding to a property grid.

Now, I need to implement a feature to "lock" position and size. I started with try and set min and max height\width to the actual height\width. The initial effort wasn't so great. And I still don't have a strategy for fixing the location.

So before I go off and wade through 25 approaches that don't work, perhaps someone has a suggestion. I'd much appreciate it.

Thanks, jeff

A: 

You could just disable the Thumb and the PropertyGrid...

Of course, for the PropertyGrid it is not ideal... it would be better to keep it enabled, but read-only, unfortunately the PropertyGrid doesn't have a ReadOnly property... A possible solution would be to wrap your object in a custom type descriptor which would present the properties as read-only. Here are two classes to achieve that (sorry for the long code...) :

ReadOnlyTypeDescriptor :

public class ReadOnlyTypeDescriptor : ICustomTypeDescriptor
{
    public ReadOnlyTypeDescriptor(object target)
    {
        TypeDescriptionProvider provider = TypeDescriptor.GetProvider(target);
        _originalDescriptor = provider.GetTypeDescriptor(target);
    }

    public ReadOnlyTypeDescriptor(ICustomTypeDescriptor descriptor)
    {
        _originalDescriptor = descriptor;
    }

    private ICustomTypeDescriptor _originalDescriptor;

    private PropertyDescriptor MakeReadOnly(PropertyDescriptor propertyDescriptor)
    {
        return new ReadOnlyPropertyDescriptor(propertyDescriptor);
    }

    private PropertyDescriptorCollection MakeReadOnly(PropertyDescriptorCollection propertyDescriptors)
    {
        var descriptors = propertyDescriptors
                            .Cast<PropertyDescriptor>()
                            .Select(pd => new ReadOnlyPropertyDescriptor(pd))
                            .ToArray();
        return new PropertyDescriptorCollection(descriptors, true);
    }

    #region ICustomTypeDescriptor Members

    public AttributeCollection GetAttributes()
    {
        return _originalDescriptor.GetAttributes();
    }

    public string GetClassName()
    {
        return _originalDescriptor.GetClassName();
    }

    public string GetComponentName()
    {
        return _originalDescriptor.GetComponentName();
    }

    public TypeConverter GetConverter()
    {
        return _originalDescriptor.GetConverter();
    }

    public EventDescriptor GetDefaultEvent()
    {
        return _originalDescriptor.GetDefaultEvent();
    }

    public PropertyDescriptor GetDefaultProperty()
    {
        return MakeReadOnly(_originalDescriptor.GetDefaultProperty());
    }

    public object GetEditor(Type editorBaseType)
    {
        return _originalDescriptor.GetEditor(editorBaseType);
    }

    public EventDescriptorCollection GetEvents(Attribute[] attributes)
    {
        return _originalDescriptor.GetEvents(attributes);
    }

    public EventDescriptorCollection GetEvents()
    {
        return _originalDescriptor.GetEvents();
    }

    public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        return MakeReadOnly(_originalDescriptor.GetProperties(attributes));
    }

    public PropertyDescriptorCollection GetProperties()
    {
        return MakeReadOnly(_originalDescriptor.GetProperties());
    }

    public object GetPropertyOwner(PropertyDescriptor pd)
    {
        return _originalDescriptor.GetPropertyOwner(pd);
    }

    #endregion
}

ReadOnlyPropertyDescriptor :

public class ReadOnlyPropertyDescriptor : PropertyDescriptor
{
    public ReadOnlyPropertyDescriptor(PropertyDescriptor descriptor)
        : base(
            descriptor.Name,
            descriptor.Attributes.Cast<Attribute>().ToArray())
    {
        _originalDescriptor = descriptor;
    }

    private PropertyDescriptor _originalDescriptor;

    public override bool CanResetValue(object component)
    {
        return false;
    }

    public override Type ComponentType
    {
        get { return _originalDescriptor.ComponentType; }
    }

    public override object GetValue(object component)
    {
        return _originalDescriptor.GetValue(component);
    }

    public override bool IsReadOnly
    {
        get { return true; }
    }

    public override Type PropertyType
    {
        get { return _originalDescriptor.PropertyType; }
    }

    public override void ResetValue(object component)
    {
        throw new NotSupportedException();
    }

    public override void SetValue(object component, object value)
    {
        throw new NotSupportedException();
    }

    public override bool ShouldSerializeValue(object component)
    {
        return _originalDescriptor.ShouldSerializeValue(component);
    }
}

To show the object target as read-only in the PropertyGrid, just do that :

propertyGrid.SelectedObject = new ReadOnlyTypeDescriptor(target);

It will show the same properties, but they won't be editable...

OK, this solution is probably a little overkill for your needs... but I think it can be handy in some cases ;)

Thomas Levesque