This project has moved. For the latest updates, please go here.

PropertyGrid + Custom Editors + ClassLibrary

Dec 17, 2014 at 3:57 PM
Edited Dec 17, 2014 at 5:27 PM
Hi,

I have many classes in my ClassLibrary. This library used in some projects. For some classes I created custom editor. But PropertyGrid placed in application don't work with my custom editors...

It's my error or it's not possible?

I have problem with refresh ExpandableObject in PropertyGrid, when I modify property. I found this topic https://wpftoolkit.codeplex.com/discussions/351469
but my class and editor in one ClassLibrary, and PropertyGrid in main application...
Developer
Dec 17, 2014 at 8:08 PM
If you create a Custom editor for specific properties of the selectedObject, the propertyGrid should use the custom editor for these properties.

Here's something that works :
//In the class library
namespace ClassLibrary1
{
    public class Class1
    {
      [Editor( typeof( FirstNameEditor ), typeof( FirstNameEditor ) )]
      public string FirstName
      {
        get;
        set;
      }

      public string LastName
      {
        get;
        set;
      }
    }

    public class FirstNameEditor : Xceed.Wpf.Toolkit.PropertyGrid.Editors.ITypeEditor
    {
      public FrameworkElement ResolveEditor( Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem propertyItem )
      {
        ComboBox comboBox = new ComboBox();
        comboBox.Foreground = new SolidColorBrush( Colors.Green );
        comboBox.ItemsSource = new List<string>() { "Tom", "Mark", "Bryan" };       
        comboBox.SelectedIndex = 0;

        //create the binding from the bound property item to the editor
        var _binding = new Binding( "Value" ); //bind to the Value property of the PropertyItem
        _binding.Source = propertyItem;
        BindingOperations.SetBinding( comboBox, ComboBox.SelectedItemProperty, _binding );
        return comboBox;
      }
    }
}

//In the Main Application :
 <Grid>
      <xctk:PropertyGrid x:Name="_propertyGrid" />
   </Grid>

 public partial class MainWindow : Window
  {
    public MainWindow()
    {
      Xceed.Wpf.Toolkit.Licenser.LicenseKey = "XXXXX-XXXXX-XXXXX-XXXX";

      InitializeComponent();    

      _propertyGrid.SelectedObject = new ClassLibrary1.Class1() { FirstName = "Tom", LastName = "Thompson"};
    }
  }
Dec 18, 2014 at 4:38 AM
You are right, it's works for simple property. See my second path in this post about refresh ExpandableObject.
public class SubClass: INotifyPropertyChanged
{
  public string FirstName { get {...}; set {...; OnPropertyChanged("FirstName")}; }
  public string LastName { get {...}; set {...; OnPropertyChanged("LastName")}; }
}

public class MyClass: INotifyPropertyChanged
{
  [ExpandableObject]
  [Editor(typeof(NameEditor), typeof(NameEditor))] // for refresh this value in PropertyGrid
  public SubClass Name { get; set; }
}

// this not used PG for my property
public class NameEditor: Xceed.Wpf.Toolkit.PropertyGrid.Editors.ITypeEditor
{
        public FrameworkElement ResolveEditor(Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem propertyItem)
        {
            TextBlock textBlock = new TextBlock();
            var binding = new Binding("Value.FirstName");
            binding.Source = propertyItem;
            binding.ValidatesOnExceptions = true;
            binding.ValidatesOnDataErrors = true;
            binding.Mode = BindingMode.OneWay;
            BindingOperations.SetBinding(textBlock, TextBlock.TextProperty, binding);
            return textBlock;
        }
}
Developer
Dec 18, 2014 at 4:35 PM
Hi,

What exactly is not working ? I used your code and the textBlock is displayed and updated when I modify the FirstName's textBox. The NameEditor.ResolveEditor() is called.
I'm using v2.3 of toolkit.
Dec 22, 2014 at 6:32 AM
Strangely...
I downloaded the source code, and looked for some reason do not work out. The problem was that the "public SubClass Name" is ReadOnly, but it is not marked with this attribute!
Dec 22, 2014 at 6:54 AM
class ObjectContainerHelperBase
private FrameworkElement GenerateChildrenEditorElement
if (pd.IsReadOnly) // always for my subclass
          editor = new TextBlockEditor(); 
Dec 22, 2014 at 10:29 AM
Sorry,
In new test project all working good...
Dec 22, 2014 at 10:51 AM
I'm understood... My properties declared as:

public SubClass Name { get; private set; }

I create instance of this property in class constructor and I don't want recreate this instance somewhere.
Dec 22, 2014 at 3:29 PM
I think it would be better not to override the custom editor, if the property is read-only. And need to change the function GenerateChildrenEditorElement in class ObjectContainerHelperBase from
            ITypeEditor editor = null;

            if (pd.IsReadOnly)
                editor = new TextBlockEditor();

            if (editor == null)
                editor = pd.CreateAttributeEditor();

            if (editor != null)
                editorElement = editor.ResolveEditor(propertyItem);
to
            ITypeEditor editor = pd.CreateAttributeEditor();

            if (editor == null && pd.IsReadOnly)
                editor = new TextBlockEditor();

            if (editor != null)
                editorElement = editor.ResolveEditor(propertyItem);
Dec 22, 2014 at 3:46 PM
And more:
may be create for read-only properties read-only TextBoxEditor (with gray foreground)? This allows you to copy the value to the clipboard.
Developer
Jan 5, 2015 at 7:15 PM
Hi,

In v2.5, the custome editor won't be override with a TextBlock when readOnly.
Same issue has https://wpftoolkit.codeplex.com/workitem/21089 and https://wpftoolkit.codeplex.com/workitem/21421.