This project has moved and is read-only. For the latest updates, please go here.

PropertyGrid: Custom Editor does not update underlying property

Feb 25, 2014 at 4:52 PM
I am trying to setup a custom editor with a combobox where in the itemssource is generated dynamically based on the value of another property. I got most of the code from other posts on this site. All appears to work visually, but the property itself is never updated.

Any thoughts on why the Database property never gets set when the combobox selection is changed?

Here is my code
    [DefaultProperty("Server")]
    public class Connection : INotifyPropertyChanged
    {
        private string _server;
        private string _database;

        
        [Xceed.Wpf.Toolkit.PropertyGrid.Attributes.PropertyOrder(1)]
        [ItemsSource(typeof (ServersItemsSource))]
        public String Server
        {
            get { return _server; }
            set
            {
                if (value == _server) return;
                _server = value;
                OnPropertyChanged();
                OnPropertyChanged("Databases");
                OnPropertyChanged("IsValid");
            }
        }

        [Xceed.Wpf.Toolkit.PropertyGrid.Attributes.PropertyOrder(2)]
        [Editor(typeof (DatabaseNameEditor), typeof (DatabaseNameEditor))]
        public String Database
        {
            get { return _database; }
            set
            {
// this is never called.
                if (value == _database) return;
                _database = value;
                OnPropertyChanged();
                OnPropertyChanged("IsValid");
            }
        }

        [Browsable(false)]
        public ObservableCollection<String> Databases
        {
            get
            {
                if (Server == null) return new ObservableCollection<string>();

                return new ObservableCollection<string>(SpeedpayMaster.Databases(Server));
            }
        }

        [Browsable(false)]
        public bool IsValid { get { return !Server.IsNullOrWhiteSpace() && !Database.IsNullOrWhiteSpace(); } }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class ServersItemsSource : IItemsSource
    {
        public ItemCollection GetValues()
        {
            
            ItemCollection sizes = new ItemCollection();
            (new List<String>() { "devdb02a", "devdb05a", "devdb07a", "qadb05a", "qadb07a", "testdb03a", "uatdb05a", "uatdb07a", "uatdb08a" }).
                ForEach(sizes.Add);
            return sizes;
        }
    }

    public class DatabaseNameEditor : ITypeEditor
    {
        public FrameworkElement ResolveEditor(PropertyItem propertyItem)
        {
            ComboBox box = new ComboBox();

            Connection source = propertyItem.Instance as Connection;
            Debug.Assert(source != null);

            var itemSourcebinding = new Binding("Databases")
            {
                Source = propertyItem.Instance,
                ValidatesOnExceptions = true,
                ValidatesOnDataErrors = true,
                Mode = BindingMode.OneWay
            };

            var selBinding = new Binding("Value")
            {
                Source = propertyItem,
                ValidatesOnExceptions = true,
                ValidatesOnDataErrors = true,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay
            };

            BindingOperations.SetBinding(box, ItemsControl.ItemsSourceProperty, itemSourcebinding);
            BindingOperations.SetBinding(box, Selector.SelectedValueProperty, selBinding);

            return box;
        }

        
    }

    
}