Incorrect editors when switching PropertySetMode

3 posts, 0 answers
  1. Chris
    Chris avatar
    18 posts
    Member since:
    Sep 2014

    Posted 09 Nov 2015 Link to this post

    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. Stefan Nenchev
    Admin
    Stefan Nenchev avatar
    281 posts

    Posted 12 Nov 2015 Link to this post

    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
  3. UI for WPF is Visual Studio 2017 Ready
  4. Chris
    Chris avatar
    18 posts
    Member since:
    Sep 2014

    Posted 12 Nov 2015 in reply to Stefan Nenchev Link to this post

    Thanks Stefan
Back to Top