.NET Forum / .NET Framework / New Users / October 2006
Custom Collection Editor - how to block the up and down buttons ?
|
|
Thread rating:  |
Robert R. Richter - 28 Sep 2006 20:22 GMT I have a Custom Collection Editor and overridden some methods - everything works fine...
BUT I now want to block the up and down buttons, so the User won't be able to move the Collection Items within the Index.
Is there any possibilty by overriding a method so it won't move the collection items?
To make it clear - I do not want to remove the buttons or make them invisible, I just want to block the functionality.
Thank you in advance, Robert.
Linda Liu [MSFT] - 29 Sep 2006 09:44 GMT Hi Robert,
I have spent several hours researching on this problem. Unfortunately, I haven't found any property or overridable method in CollectionEditor class to disable the up and down buttons in the collection editor dialog.
I have tried to override the EditValue method. In the overridden EditValue method, the line of code 'base.EditValue(context, provider, value);' displays the collection editor dialog. But it's hard to get the dialog. And even if we could get the dialog, it might be impossible to disable the up and down button in the dialog, for the dialog may not expose such a property or method to allow us to do it.
Coud you tell me why you want to disable the up and down buttons in the collection dialog? In my opinion, this function is very convenience for the user.
I will go on researching on this issue and as soon as I have a new finding, I will get it back to you.
Have a nice weekend!
Sincerely, Linda Liu Microsoft Online Community Support
================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications. Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Robert R. Richter - 29 Sep 2006 11:42 GMT Hi Linda!
I have one Collection, which holds 'Distances' (in meters - declared as float), but it's vital that it has some kind of sort order.
I have already (successfully) done some tricks to keep these values in order, even if the user adds new values via dialog 'add' button ;) ... - with 'in order' I mean the index of the Collection, i.e. index[0] 100 / index[1] 200 / index[2] 500, so if one adds a new value of 300, the collection will look like this: index[0] 100 / index[1] 200 / index[2] 300 / index[3] 500...
If the 'add' button is pushed the newly added distance will be set to a value of 100(m) greater than the last element in the collection shows and if someone sets a new value the collection is resorted automatically ;) ...
This is done by some (ugly ;) ) code within the Set Accessor like this:
/// <summary> /// lod_distance of lod_distances. /// </summary> [Bindable(false), Category("Excelsior - Data"), Description("lod_distance of lod_distances.")] public float lod_distance { get { return this.m_lod_distance; } set { if (value <= 0) return; this.m_lod_distance = value; // mighty nasty Hack, but I **REALLY** LOVE IT ;) if (Convert.ToBoolean(Excelsior.Win32specific.Win32Registry.ReadObjectFromRegistry(Excelsior.Win32specific.ExcelsiorProjectIdentifier.EPI_TOOLSET, "ReorgFlag"))) return; Excelsior.Win32specific.Win32Registry.WriteObjectToRegistry(Excelsior.Win32specific.ExcelsiorProjectIdentifier.EPI_TOOLSET, "ReorgFlag", 1); float[] sortDistances = new float[((Material)this.Parent).lod_distances.Count]; for (int i = 0; i < ((Material)this.Parent).lod_distances.Count; i++) { sortDistances[i] = ((Material)this.Parent).lod_distances[i].lod_distance; } Array.Sort(sortDistances); for (int i = 0; i < ((Material)this.Parent).lod_distances.Count; i++) { ((Material)this.Parent).lod_distances[i].lod_distance = sortDistances[i]; } Excelsior.Win32specific.Win32Registry.WriteObjectToRegistry(Excelsior.Win32specific.ExcelsiorProjectIdentifier.EPI_TOOLSET, "ReorgFlag", 0); } }
This is possible because the Collection is a property of another class and holds a refernce to the parent object - was really hard to get the Parent object set if an item is added via Collection Editor 'add'-Button, but I got this up and running ;) using this Code:
/// <summary> /// override CreateInstance to implement our wanted behavior, /// setting a Reference to the Parent (Material) object, /// which holds the LoD_Distance Collection. /// </summary> protected override object CreateInstance(Type ItemType) { LoD_Distance lod = (LoD_Distance)base.CreateInstance(ItemType); if (this.Context.Instance != null) { if (this.Context.Instance is Material) { lod.SetParentObject((Material)this.Context.Instance); float[] sortDistances = new float[((Material)this.Context.Instance).lod_distances.Count]; for (int i = 0; i < ((Material)this.Context.Instance).lod_distances.Count; i++) { sortDistances[i] = ((Material)this.Context.Instance).lod_distances[i].lod_distance; System.Diagnostics.Debug.WriteLine(sortDistances[i].ToString()); } Array.Sort(sortDistances); if (sortDistances.Length >= 1) lod.lod_distance = sortDistances[sortDistances.Length - 1] + 100; else lod.lod_distance = 100; } } return lod; }
So everythings work fine, until the User moves the Collection Items via the up/down Buttons, so I just want to get notified if this 'event' happens, so I can resort my Collection again, as I did in the Code above.
Actually it is not necessary to 'block' the buttons, I am searching for a way to get notified that one of the buttons has been pushed, so I can re-sort my Collection Items to get this undone...
Thank you for your help!
Robert
> Hi Robert, > [quoted text clipped - 41 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Linda Liu [MSFT] - 02 Oct 2006 06:45 GMT Hi Robert,
Thank you for your detailed explaination. I understand why you want to block the up and down buttons in the collection editor dialog now.
To get notified when one of the up and down buttons is pushed, we would have two possible ways. One is to handle some event of the collection editor dialog and the other is to handle some event of the collection.
As for the first 'option', we couldn't even get the collection editor dialog. Say nothing of handling some event of the editor dialog. As for the second 'option', I don't know which type the collection is in your project. The type of the collection in my test project is List<T>, which hasn't even one event.
So it seems that the two possible candidates aren't feasible.
In fact, since CollectionEditor is inherited from UITypeEditor and implement the EditValue method to popup the collection editor dialog and return the collection, we could override the EditValue method and re-sort the collection after the collection editor dialog is closed.
The following is a sample of overriding the EditValue method.
public class MyCollectionEditor:CollectionEditor { public MyCollectionEditor(Type type):base(type) { } public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { object ins = base.EditValue(context, provider, value); if (context.Instance != null) { if (context.Instance is Material) { // add your code to re-sort the collection in the Material object, e.g ((Material)context.Instance).SortList(); } } return ins; } }
Since we need to re-sort the collection out of the LoD_Distance class, I recommend you to add a method in the Material class to re-sort the collection in it. And make some small modifications in the LoD_Distance class. The following is a sample.
using System.Collections.Generic; using System.Drawing.Design; using System.ComponentModel;
class Material { private List<LoD_Distance> lists = new List<LoD_Distance>(); [Editor(typeof(MyCollectionEditor),typeof(UITypeEditor))] public List<LoD_Distance> lod_distances { get { return lists; } } public Material() { } public void SortList() { float[] sortDistances = new float[this.lod_distances.Count]; for (int i = 0; i < this.lod_distances.Count; i++) { sortDistances[i] = this.lod_distances[i].lod_distance; }
Array.Sort(sortDistances); for (int i = 0; i < this.lod_distances.Count; i++) { this.lod_distances[i].needsorting = false; this.lod_distances[i].lod_distance = sortDistances[i]; this.lod_distances[i].needsorting = true; } } }
class LoD_Distance { public bool needsorting = true;
[Bindable(false),Category("Excelsior - Data"),Description("lod_distance of lod_distances.")] public float lod_distance { get { return this.m_lod_distance; } set { if (value <= 0) return; this.m_lod_distance = value;
if (needsorting == true) { this.parent.SortList(); } } }
private float m_lod_distance=0; private Material parent = null; public Material Parent { get { return parent; } } public void SetParentObject(Material obj) { parent = obj; } }
Hope this helps. If you have anything unclear, please feel free to let me know.
Sincerely, Linda Liu Microsoft Online Community Support
Petar Repac - 02 Oct 2006 21:56 GMT Hi Linda and Robert,
1. About second option Linda mentioned, maybe one could use System.Collections.CollectionBase as base class for collection in question. This class provides protected virtual events like OnInsert, OnRemove, OnClear.
2) According to http://www.codeproject.com/csharp/DzCollectionEditor.asp CollectionEditor works with IList, so one could implement a class that implements IList and trace how CollectionEditor move items up or down. By knowing this implementation can be changed to prevent moving of items up or down.
Hope it helps.
Petar Repac
Robert R. Richter - 03 Oct 2006 23:34 GMT Hi Linda, hi Peter!
First I want to thank Linda for her information, helped me a lot...
I think overriding the EditValue Method will be my favorite solution - it's really ok to start sorting on closing the Editor...
> 1. About second option Linda mentioned, > maybe one could use System.Collections.CollectionBase as > base class for collection in question. > This class provides protected virtual events like OnInsert, OnRemove, > OnClear. I am already deriving my Collection from CollectionBase, nice to know that there are events which can be used - I 'll look into this soon... - thank you, Peter!
> 2) According to > http://www.codeproject.com/csharp/DzCollectionEditor.asp > CollectionEditor works with IList, so one could implement a class that > implements IList and trace how CollectionEditor move items up or down. > By knowing this implementation can be changed to prevent moving of items > up or down. Sounds not easy - I have already looked at Collection Editor's code, but it's not easy to understand - I must admit that I would have coded Collection Editor much simpler than MS did ;) - but I am far away from writing such complex things like .NET Framework - so I think your second suggestion is too time consuming to implement - at least for me ;) !
Thank you Linda, thank you Peter!
Robert
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|