This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hi, According to Mindscape manual, the property grid built-in editor supports validation throwing exceptions or implementing the IDataErrorInfo interface. I created a class derived from ObservableDictionary and I implemented the IDataErrorInfo interface, then I set the object to the ItemsSource of the propertyGrid, I also registered to the PropertyChanged event of the ObservableDictionary. What happens is that when some value changes I don't know which key of the dictionary is being changed, and I always receive the property name "Items" in the event or in the this parameter of the IDataErrorInfo interface. Do you have some suggestion for me to validate the fields independently ? Please find below some pieces of the source code, and a figure attached : Dictionary Class definition: public class MyDictionary : ObservableDictionary<Entries, object>, IDataErrorInfo { ... } Main code: itemsSource = new MyDictionary();for (int i=0; i< numberOfEntries; i++) itemsSource.Add(entry, value); propertyGrid.ItemsSource = itemsSource;
Thanks |
|
|
Unfortunately, I don't think there's a way around this, because the IDataErrorInfo call is happening from within WPF, and WPF is being quite literal about the property name. What you can do instead is trick WPF into seeing properties instead of dictionary entries. This is a bit laborious but not too difficult. Note that if you do this you must set propertyGrid.SelectedObject = myDictionary, rather than ItemsSource -- that is, telling the grid to treat the dictionary as an object with properties, rather than a dictionary with entries. How do you trick WPF into seeing properties where there are really only dictionary entries? There are a number of possibly approaches including TypeConverter, TypeDescriptionProvider and ICustomTypeDescriptor. I'm going to describe an approach based on ICustomTypeDescriptor because I think that's the most appropriate when the faux property behaviour is inherent in the class, but the same general techniques apply to the other methods as well. So on your MyDictionary class, implement ICustomTypeDescriptor: public class MyDictionary : ObservableDictionary<Entry, object>, IDataErrorInfo, ICustomTypeDescriptor Now you have a truckload of methods to implement. The important one is GetProperties. In your GetProperties implementation, you're going to create a collection of PropertyDescriptors that represent your dictionary keys. The bad news is that to do this you have to create a custom class derived from PropertyDescriptor. This will look something like this: private class MyDictionaryEntryDescriptor : PropertyDescriptor { (There are some other methods and properties you'll need to implement but these are generally trivial or can just throw a NotImplementedException -- let me know if you need more info.) You can see what we're doing here: we're describing a property, but when WPF tries to get or set that property's value, we're mapping that into a dictionary get or set. Now our ICustomTypeDescriptor.GetProperties method is reasonably simple: public PropertyDescriptorCollection GetProperties() { Most of the other ICustomTypeDescriptor members can be given trivial implementations for property grid purposes. Again, let me know if you need more info. With these changes in place, you can change your code to: itemsSource = new MyDictionary(); and you should now get the entry name being passed to IDataErrorInfo. Please note this won't help with the PropertyChanged stuff. One alternative is to subscribe to CollectionChanged but this is still list-oriented and may not be too helpful with a dictionary. However the best best is probably to have your PropertyDescriptor.SetValue implementation call the dictionary's OnPropertyChanged event passing the name of the ersatz property. However some care may be required here if your PropertyChanged event handler plans to use the property name -- you will get a mixture of "real" PropertyChanged events (for Item[] and Count) and "synthetic" ones (for dictionary entries) and it will be up to you to distinguish the two. Hope this helps! |
|
|
Hi, I am sure this is good enough to solve my problem, you have also opened my mind for a lot of new ideas. Another way that I found is to use the member: "propertyGrid.SelectedGridItem.Node.HumanName" that contains the name of the property too, so I can search for the item in the dictionary using this "HumanName", but in this case, it does not use IDataErrorInfo, I must throw the exceptions on validate errors and I am afraid of performance issues due to exceptions system resources consumption : KeyValuePair <Entries, object> item;ObservableDictionary <Entries, object> itemsSource;string propertyName = propertyGrid.SelectedGridItem.Node.HumanName;item = System.Linq. Enumerable.First<KeyValuePair<Entries, object>>(itemsSource, entry => entry.Key.Name == propertyName);
I will implement the solutions above and find the better manner to solve my problem. Thank you very much for your suggestion. Rafael |
|
|
The font of the code is smaller, but it semms to fit better : KeyValuePair<Entries, object> item; ObservableDictionary <Entries, object> itemsSource;string propertyName = propertyGrid.SelectedGridItem.Node.HumanName; item = System.Linq.Enumerable.First<KeyValuePair<Entries, object>>(itemsSource, entry => entry.Key.Name == propertyName);
|
|
|
[quote user="rafael"]in this case, it does not use IDataErrorInfo, I must throw the exceptions on validate errors and I am afraid of performance issues due to exceptions system resources consumption[/quote] I wouldn't worry about the cost of throwing exceptions from a data binding. Remember that this is all happening in "user interaction time." Suppose, worst case, that you were throwing an exception on every keystroke. The time between two keystrokes is an aeon in CPU time; the cost of the exception is microscopic compared to the time the computer spends idling waiting for the user's finger to travel to the next key. Optimising away exceptions can be relevant in heavily loaded scenarios like Web server code or tight loops, but for code that's responding to interactive events, it's almost never worth worrying about. |
|