This is a migrated thread and some comments may be shown as answers.

Incorrect editors when switching PropertySetMode

2 Answers 76 Views
PropertyGrid
This is a migrated thread and some comments may be shown as answers.
Chris
Top achievements
Rank 1
Chris asked on 09 Nov 2015, 09:35 PM

I'm experiencing some odd behavior when changing the PropertySetMode at runtime. 

 

I have two object types: MyTestClass1 and MyTestClass2. MyTestClass1 has a writeable property IntProp and MyTestClass2 has a readonly property IntProp. If I start in Intersection mode with Item = List<Object> { myTestClass1Obj1, myTestClass1Obj2 } everything works properly. If I then change to PropertySetMode None with Item = myTestClass2Obj, the editor for IntProp will be writeable even though IntProp on myTestClass2Obj has no public setter.

 

See runnable test case below. I am running 2015.2.728

<Window x:Class="WpfApplication1.MainWindow"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
        Title="MainWindow" Height="350" Width="525">
    <Grid>
    <StackPanel Orientation="Vertical">
      <Button Click="ButtonBase_OnClick">Change to mode none</Button>
      <telerik:RadPropertyGrid x:Name="rpg"/>
    </StackPanel>
  </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.ComponentModel.DataAnnotations;
using Telerik.Windows.Controls.Data.PropertyGrid;
 
namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
      private readonly MyTestClass test;
    private readonly MyTestClass test2;
    private readonly MyTestClass2 test3;
 
    public MainWindow()
        {
            InitializeComponent();
            rpg.AutoGeneratingPropertyDefinition += new EventHandler<Telerik.Windows.Controls.Data.PropertyGrid.AutoGeneratingPropertyDefinitionEventArgs>(rpg_AutoGeneratingPropertyDefinition);
 
      // test data. IntProp is has a public setter
      test = new MyTestClass() { StringProp = "91das", RequiredField = "abc", IntProp = 10, DateTimeProp = new DateTime(1920, 2, 21) };
      test2 = new MyTestClass() { StringProp = "91das", RequiredField = "abc", IntProp = 10, DateTimeProp = new DateTime(1920, 2, 21) };
 
      // test data. IntProp is read only (no public setter)
      test3 = new MyTestClass2() { StringProp = "91das", RequiredField = "abc", DateTimeProp = new DateTime(1920, 2, 21) };
 
      rpg.Item = new List<Object> {test, test2};
      rpg.PropertySetMode = PropertySetOperation.Intersection;
        }
 
        void rpg_AutoGeneratingPropertyDefinition(object sender, Telerik.Windows.Controls.Data.PropertyGrid.AutoGeneratingPropertyDefinitionEventArgs e)
        {
            (e.PropertyDefinition.Binding as Binding).ValidatesOnDataErrors = true;
            (e.PropertyDefinition.Binding as Binding).NotifyOnValidationError = true;
            (e.PropertyDefinition.Binding as Binding).ValidatesOnExceptions = true;
        }
 
        private ObservableCollection<ValidationError> results;
 
        public ObservableCollection<ValidationError> Results
        {
            get
            {
                if (this.results == null)
                {
                    this.results = new ObservableCollection<ValidationError>();
                }
                return results;
            }
        }
     
    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
      rpg.PropertySetMode = PropertySetOperation.None;
      rpg.Item = test3;
      // the property grid will now allow setting of test3.IntProp even though there is
      // no public setter
    }
  }
 
 
    public class MyTestClass : IDataErrorInfo, INotifyPropertyChanged
    {
         
        private int intVar;
        private string requiredField;
 
        public int IntProp
        {
            get { return intVar; }
            set
            {
                intVar = value;
                this.OnPropertyChanged("IntProp");
            }
        }
 
        [Required(ErrorMessage = "This field is Required.")]
        public string RequiredField
        {
            get { return requiredField; }
            set
            {
                requiredField = value;
                ValidateProperty("RequiredField", value);
                this.OnPropertyChanged("RequiredField");
            }
        }
 
        private string stringVar;
 
        public string StringProp
        {
            get { return stringVar; }
            set
            {
                stringVar = value;
                this.OnPropertyChanged("StringProp");
            }
        }
 
        private DateTime dateTimeVar;
 
        public DateTime DateTimeProp
        {
            get { return dateTimeVar; }
            set
            {
                dateTimeVar = value;
                this.OnPropertyChanged("DateTimeProp");
            }
        }
 
        [Browsable(false)]
        public string Error
        {
            get { return string.Empty; }
        }
 
        public string this[string columnName]
        {
            get
            {
                if (columnName == "IntProp")
                {
                    return this.IntProp < 100 && this.IntProp > 0 ? string.Empty : "Value should be in the range of (0, 100)";
                }
                if (columnName == "StringProp")
                {
                    return this.StringProp != null && Regex.IsMatch(this.StringProp, @"^[0-9]+[\p{L}]*") ? string.Empty : @"Value should math the regex: ^[0-9]+[\p{L}]*";
                }
                if (columnName == "DateTimeProp")
                {
                    return this.DateTimeProp.Year > 1900 ? string.Empty : "Date should be after 1/1/1900";
                }
                return string.Empty;
            }
        }
 
        protected void OnPropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        public void ValidateProperty(string propName, object value)
        {
            var result = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
            Validator.TryValidateProperty(value, new ValidationContext(this, null, null) { MemberName = propName }, result);
 
            if (result.Count > 0)
            {
               throw new ValidationException(result[0].ErrorMessage);
            }
        }
    }
 
 
  public class MyTestClass2 : IDataErrorInfo, INotifyPropertyChanged
  {
 
    private int intVar;
    private string requiredField;
 
    public int IntProp { get; } = 12;
 
    [Required(ErrorMessage = "This field is Required.")]
    public string RequiredField
    {
      get { return requiredField; }
      set
      {
        requiredField = value;
        ValidateProperty("RequiredField", value);
        this.OnPropertyChanged("RequiredField");
      }
    }
 
    private string stringVar;
 
    public string StringProp
    {
      get { return stringVar; }
      set
      {
        stringVar = value;
        this.OnPropertyChanged("StringProp");
      }
    }
 
    private DateTime dateTimeVar;
 
    public DateTime DateTimeProp
    {
      get { return dateTimeVar; }
      set
      {
        dateTimeVar = value;
        this.OnPropertyChanged("DateTimeProp");
      }
    }
 
    [Browsable(false)]
    public string Error
    {
      get { return string.Empty; }
    }
 
    public string this[string columnName]
    {
      get
      {
        if (columnName == "IntProp")
        {
          return this.IntProp < 100 && this.IntProp > 0 ? string.Empty : "Value should be in the range of (0, 100)";
        }
        if (columnName == "StringProp")
        {
          return this.StringProp != null && Regex.IsMatch(this.StringProp, @"^[0-9]+[\p{L}]*") ? string.Empty : @"Value should math the regex: ^[0-9]+[\p{L}]*";
        }
        if (columnName == "DateTimeProp")
        {
          return this.DateTimeProp.Year > 1900 ? string.Empty : "Date should be after 1/1/1900";
        }
        return string.Empty;
      }
    }
 
    protected void OnPropertyChanged(string name)
    {
      if (this.PropertyChanged != null)
      {
        this.PropertyChanged(this, new PropertyChangedEventArgs(name));
      }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    public void ValidateProperty(string propName, object value)
    {
      var result = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
      Validator.TryValidateProperty(value, new ValidationContext(this, null, null) { MemberName = propName }, result);
 
      if (result.Count > 0)
      {
        throw new ValidationException(result[0].ErrorMessage);
      }
    }
  }
}
 

 

dafadsf

2 Answers, 1 is accepted

Sort by
0
Stefan Nenchev
Telerik team
answered on 12 Nov 2015, 03:56 PM
Hello Chris,

I have reproduced the scenario you explained and after some further investigation from my end I can confirm there is an issue when updating the PropertySetMode at runtime. I have logged this behavior as a bug and you can follow it on our Ideas and Feedback Portal.  You can click on "Following this item"  in order to subscribe for notifications. I have also added 1000 Telerik points to your account as a compliment for reporting the matter.

Regards,
Stefan Nenchev
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Chris
Top achievements
Rank 1
answered on 12 Nov 2015, 04:26 PM
Thanks Stefan
Tags
PropertyGrid
Asked by
Chris
Top achievements
Rank 1
Answers by
Stefan Nenchev
Telerik team
Chris
Top achievements
Rank 1
Share this question
or