471,594 Members | 2,301 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,594 software developers and data experts.

KeyedCollection in use for GUI editor? Chicken in Egg problem...

So when you use VS's View Designer, each object included is keyed off
its Name. You cannot make the name the same as some other component.
You can change the name in a PropertyGrid. I want to do a similar
thing. I have a class (MissionManager with a bunch of static functions)
that contains a static KeyedCollection<Missionof my objects. Each
mission has a Name (and interface requring the name). That works fine.
What doesn't work is changing the name in the PropertyGrid; that
doesn't update the index in the KeyedCollection. How do other people
handle this issue?

Dec 12 '06 #1
3 1848
Hi,

1. By "VS View Designer" do you mean the Windows Forms Designer? The "View
Designer" is for databases.

2. It's not clear what you are doing, but I assume that you are setting the
PropertyGrid.SelectedObject property to an instance of your Mission class
that is also contained by your static KeyedCollection and you're wondering
why a change to the Name property using the PropertyGrid doesn't appear to
be updating the instance within the collection.

You should supply a short but complete example of the problem you are having
so that we can better assist you (see Jon Skeet's guidance on short but
complete programs here: http://www.yoda.arachsys.com/csharp/complete.html)

--
Dave Sexton

"Brannon" <br*********@yahoo.comwrote in message
news:11**********************@j72g2000cwa.googlegr oups.com...
So when you use VS's View Designer, each object included is keyed off
its Name. You cannot make the name the same as some other component.
You can change the name in a PropertyGrid. I want to do a similar
thing. I have a class (MissionManager with a bunch of static functions)
that contains a static KeyedCollection<Missionof my objects. Each
mission has a Name (and interface requring the name). That works fine.
What doesn't work is changing the name in the PropertyGrid; that
doesn't update the index in the KeyedCollection. How do other people
handle this issue?

Dec 13 '06 #2
Thanks for replying.
1. By "VS View Designer" do you mean the Windows Forms Designer? The "View
Designer" is for databases.
I do mean the Windows Forms Designer.
2. It's not clear what you are doing, but I assume that you are setting the
PropertyGrid.SelectedObject property to an instance of your Mission class
that is also contained by your static KeyedCollection
That's exactly correct.
and you're wondering
why a change to the Name property using the PropertyGrid doesn't appear to
be updating the instance within the collection.
I'm not wondering why the KeyedCollection key is not updated. I'm
wondering 1) what is the best way to make it automatically update the
KeyedCollection indexing, 2) what is the best way to make the
PropertyGrid disallow existing keys from the collection, and 3) what is
the best way to generate an instance name similar to the way the Forms
Designer generates names for instances.

Thanks again.

Dec 13 '06 #3
Hi,

<snip>
1) what is the best way to make it automatically update the
KeyedCollection indexing,
You have to update it yourself using the ChangeItemKey method when the Name
property changes. There are a few different ways to accomplish that. I've
posted code that uses an event, after my sig.
2) what is the best way to make the
PropertyGrid disallow existing keys from the collection
That behavior exists already in my example code below. The ChangeItemKey
method throws an ArgumentException stating, "An item with the same key has
already been added". I've caught and rethrown it with a more meaningful
message. The PropertyGrid suppresses the exception and displays a special
message box containing a predefined message with my wrapper message as
details.
3) what is
the best way to generate an instance name similar to the way the Forms
Designer generates names for instances.
Check out the MissionManager class after my sig. Specifically, the
CreateUniqueName method.

I haven't added comments because the code seems self-explanatory to me, but
if anything is unclear just let me know and I'll explain it.

--
Dave Sexton
static class MissionManager
{
public static readonly MissionCollection Missions = new
MissionCollection();

public static string CreateUniqueName()
{
string name = "Mission_";
int i = Missions.Count + 1;

while (Missions.Contains(name + i))
i++;

return name + i;
}
}

class Mission
{
public string Name
{
get
{
return name;
}
set
{
if (name == value)
return;

OnNameChanging(new NameChangingEventArgs(value));

name = value;
}
}

private string name;

public Mission(string name)
{
this.name = name;
}

private readonly object NameChangingEventLock = new object();
private EventHandler<NameChangingEventArgsNameChangingEven t;

/// <summary>
/// Event raised when the <see cref="Name" /property value is about to
be changed.
/// </summary>
public event EventHandler<NameChangingEventArgsNameChanging
{
add
{
lock (NameChangingEventLock)
{
NameChangingEvent += value;
}
}
remove
{
lock (NameChangingEventLock)
{
NameChangingEvent -= value;
}
}
}

/// <summary>
/// Raises the <see cref="NameChanging" /event.
/// </summary>
/// <param name="e"><see cref="NameChangingEventArgs" /object that
contains the new name for the property.</param>
protected virtual void OnNameChanging(NameChangingEventArgs e)
{
EventHandler<NameChangingEventArgshandler = null;

lock (NameChangingEventLock)
{
handler = NameChangingEvent;

if (handler == null)
return;
}

handler(this, e);
}
}

class NameChangingEventArgs : EventArgs
{
public string NewName { get { return newName; } }
private readonly string newName;

public NameChangingEventArgs(string newName)
{
this.newName = newName;
}
}

class MissionCollection : KeyedCollection<string, Mission>
{
protected override void InsertItem(int index, Mission item)
{
item.NameChanging += HandleNameChange;
base.InsertItem(index, item);
}

protected override void SetItem(int index, Mission item)
{
item.NameChanging += HandleNameChange;
base.SetItem(index, item);
}

protected override void RemoveItem(int index)
{
this[index].NameChanging -= HandleNameChange;
base.RemoveItem(index);
}

protected override void ClearItems()
{
foreach (Mission mission in this)
mission.NameChanging -= HandleNameChange;

base.ClearItems();
}

private void HandleNameChange(object sender, NameChangingEventArgs e)
{
try
{
base.ChangeItemKey((Mission) sender, e.NewName);
}
catch (ArgumentException ex)
{
throw new ArgumentException("The specified Name is already in use by
another Mission.", ex);
}
}

protected override string GetKeyForItem(Mission item)
{
return item.Name;
}
}
Dec 14 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by James T. | last post: by
reply views Thread by Craig Buchanan | last post: by
3 posts views Thread by Wiebe Tijsma | last post: by
10 posts views Thread by Chris Mullins [MVP] | last post: by
8 posts views Thread by GS | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by
reply views Thread by Anwar ali | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.