locked
WPF DataGrid and ITypedList: PropertyDescriptor.GetValue() is not called RRS feed

  • Question

  • I tried to implement ITypedList in my ItemsSourcebut PropertyDescriptor.GetValue/SetValue are never invoked. What is wrong about it?

    XAML looks like this:

    <Window x:Class="WpfApplication5.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            xmlns:local="clr-namespace:WpfApplication5"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <DataGrid AutoGenerateColumns="True">
                <DataGrid.ItemsSource>
                    <local:RowCollection/>
                </DataGrid.ItemsSource>
            </DataGrid>
        </Grid>
    </Window>


    RowCollection is defined as:

    public class RowCollection : ReadOnlyCollection<Row>, ITypedList {
        readonly PropertyDescriptorCollection _properties;
    
        public RowCollection() : base(new List<Row>()) {
            _properties = new PropertyDescriptorCollection(new[] {
                    new RowDescriptor("Name"),
                    new RowDescriptor("Value")
            }, true);
    
            Items.Add(new Row());
            Items.Add(new Row());
        }
    
        PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) {
            return _properties;
        }
    
        string ITypedList.GetListName(PropertyDescriptor[] listAccessors) {
            return null;
        }
    }



    Where RowDescriptor is:

    public class RowDescriptor : PropertyDescriptor {
        public RowDescriptor(string name) 
            : base(name, new Attribute[0]) {
        }
    
        public override bool CanResetValue(object component) {
            return false;
        }
    
        public override Type ComponentType {
            get { return typeof(Row); }
        }
    
        public override object GetValue(object component) {
            var row = (Row)component;
            return row[Name];
        }
    
        public override bool IsReadOnly {
            get { return false; }
        }
    
        public override Type PropertyType {
            get { return typeof(string); }
        }
    
        public override void ResetValue(object component) {
            throw new NotSupportedException();
        }
    
        public override void SetValue(object component, object value) {
            var row = (Row)component;
            row[Name] = String.Format("{0}", value ?? String.Empty);
        }
    
        public override bool ShouldSerializeValue(object component) {
            return false;
        }
    }
    

    And Row is:

    public class Row {        
        readonly Dictionary<string, string> _values;
    
        public Row() {
            _values = new Dictionary<string, string>();
            this["Name"] = "Foo";
            this["Value"] = "Bar";
        }
    
        public string this[string name] {
            get {
                if (!_values.ContainsKey(name))
                    return String.Empty;
    
                return _values[name];
            }
            set {
                _values[name] = value;
            }
        }
    }


    Wednesday, June 5, 2013 5:06 PM

Answers

  • Hi Dmitry Nogin,

    In WPF, DataBinding will be set up for each individual item, so WPF will not go through ITypeList to retrieve the property value of the items.

    You can implement ICustomTypeDesciptor for the item class to resolve the issue.

    Here is a quick sample.

        public class Row :CustomTypeDescriptor
        {
    
            public override PropertyDescriptorCollection GetProperties()
            {
                return new PropertyDescriptorCollection(new[] {
                    new RowDescriptor("Name"),
                    new RowDescriptor("Value")
            }, true);
            }

    Best regards,

    Min Zhu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Dmitry Nogin Tuesday, June 11, 2013 5:15 PM
    Monday, June 10, 2013 8:38 AM

All replies

  • Any chance you can give us some code that we can just drop into visual studio and run?
    • Edited by Min Zhu _ Friday, June 7, 2013 2:32 PM
    Friday, June 7, 2013 2:32 PM
  • Thank you for your attention. It would be a big deal for me to know if you can reproduce this behavior.

    The complete solution includes all the quoted code and nothing else. I do not know how to attach a file to the post here, so I just put it on http://nogin.info/WpfApplication1.zip


    Friday, June 7, 2013 4:17 PM
  • Hi Dmitry Nogin,

    In WPF, DataBinding will be set up for each individual item, so WPF will not go through ITypeList to retrieve the property value of the items.

    You can implement ICustomTypeDesciptor for the item class to resolve the issue.

    Here is a quick sample.

        public class Row :CustomTypeDescriptor
        {
    
            public override PropertyDescriptorCollection GetProperties()
            {
                return new PropertyDescriptorCollection(new[] {
                    new RowDescriptor("Name"),
                    new RowDescriptor("Value")
            }, true);
            }

    Best regards,

    Min Zhu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Dmitry Nogin Tuesday, June 11, 2013 5:15 PM
    Monday, June 10, 2013 8:38 AM