RefreshProperties problem in Visual Studio Designer

J

josephbubba

I'm having a problem updating the properties of a control in the
Visual Studio Designer property grid. A summary of the control:

1. I have a control derived from ListBox (ReorderListBox).
2. I have added an additional property (AllowReorder) which when set
to true forces the AllowDrop property to true. (This allows the user
to reorder items in the list box using drag and drop).
3. I marked the AllowReorder property with the
RefreshProperties(RefreshProperties.All) attribute so that whenever
the propert is changed it *should* force the update of all the other
properties.

I have tested the control in a standalone Windows Form application
that has a property grid. Whenever I modify the AllowReorder property
the AllowDrop property is properly updated.

Now the problem:

When I try and do the same thing in the Visual Studio Designer
property grid, a modification to AllowReorder does NOT trigger an
update request for the AllowDrop property.

I've stepped through the code with the debugger. I tried launching
the Visual Studio (devenv.exe) as a debug client to see when other
properties are updated. All of the other properties (I added some
additional properties for testing) are being reread when AllowReorder
is modified.

I even tried overriding the virtual AllowDrop method and adding trace
messages to see if it is called. No luck. It is never called when
used within the Visual Studio designer.

As I mentioned previously, it all works fine when used with a standard
property grid. It just doesn't work within Visual Studio.

I have some theories:
1. Because my class is derived from ListBox, some other attribute is
overriding?
2. Because AllowDrop is virtual the designer doesn't know how to
handle it?


Any ideas would be appreciated.
Thanks in advance.




Some code for reference:

public partial class ReorderListBox : ListBox
{
// private members
private bool _allowReorder = true; // allow reordering by
drag and drop

/// <summary>
/// Constructor
/// </summary>
public ReorderListBox()
{
// forms designer support
InitializeComponent();

// allow drag and drop (otherwise the OnDrag... overrides
below won't get called)
AllowDrop = true;

// only single select mode is currently supported
SelectionMode = SelectionMode.One;
}


// some unrelated code here removed for brevity...


/// <summary>
/// Property to get/set the "allow reordering" logic.
/// </summary>
[Category("Behavior")]
[Description("Indicates whether drag and drop can be used to
reorder items in the listbox.")]
[DefaultValue(true)]
[Browsable(true)]
[RefreshProperties(RefreshProperties.All)]
public bool AllowReorder
{
get
{
return _allowReorder;
}
set
{
if (value) AllowDrop = true; // make sure drag
and drop is enabled
_allowReorder = value;
}
}

}
 
M

Marc Gravell

From your description, it sounds like it should already work - but
clearly it isn't.

Looking at the class, it doesn't provide change-notification on this
property (AllowDrop); one option, then, is to provide this yourself.
Due to some nuances of the component-model [*], the best approach here
is to provide a "new" AllowDrop, along with the notification event;
something like:

public class ReorderListBox : ListBox
{
public new bool AllowDrop
{
get { return base.AllowDrop; }
set {
if (value != AllowDrop)
{
base.AllowDrop = value;
OnAllowDropChanged();
}
}
}

private bool _someOtherForcingProperty = false;
[DefaultValue(false)]
public bool SomeOtherForcingProperty
{
get { return _someOtherForcingProperty; }
set
{
if (value != SomeOtherForcingProperty)
{
_someOtherForcingProperty = value;
OnAllowDropChanged(); // force-refresh AllowDrop
}
}
}
private static readonly object EVENT_AllowDropChanged = new
object();
public event EventHandler AllowDropChanged
{
add { Events.AddHandler(EVENT_AllowDropChanged, value); }
remove { Events.RemoveHandler(EVENT_AllowDropChanged,
value); }
}
protected void OnAllowDropChanged()
{
EventHandler handler = Events[EVENT_AllowDropChanged] as
EventHandler;
if (handler != null) handler(this, EventArgs.Empty);
}
}

Does that work at all? I haven't checked myself...

The * above is due to PropertyDescriptor; IIRC, the default
implementation uses .ComponentType to look for notification events,
which would otherwise return typeof(ListBox) which doesn't have an
AllowDropChanged; by using "new", the .ComponentType is
typeof(ReorderListBox), which does.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top