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:telerik="http://schemas.telerik.com/2008/xaml/presentation" 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