Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.1k views
in Technique[技术] by (71.8m points)

c# - Why is my implementation of a custom TypeDescriptor to retrieve second-level property for DataGridView not working?

I am trying to implement Linda Liu's solution for displaying second-level properties in a DataGridView. If I'm understanding everything correctly, when a DataSource is set, C# uses a method called ICustomTypeDescriptor.GetProperties, which "grabs" PropertyDescriptors from the class module and adds them to a collection. So Liu's solution is to create PropertyDescriptors for the second level properties and to return them along with the original PropertyDescriptors.

In my case, EmployeeModel has a property JobTitle. JobTitle has properties Name and ID. My SQL joins these and returns a list of EmployeeModel with JobTitle.Name and JobTitle.ID set. I want to display JobTitle.Name as a column in EmployeeGridView. (When I've managed to make this work, I'll do the same for several other properties of EmployeeModel.)

Everything compiles, but at runtime the effect is not achieved. I end up with an extra column with no visible content, while the original JobTitle column is replicated as the rightmost column.

Screenshot of my application

namespace WorkDesk_Library.Binding_Assist
{
    class MyTypeDescriptionProvider : TypeDescriptionProvider
    {
        private ICustomTypeDescriptor td;

        public MyTypeDescriptionProvider()
           : this(TypeDescriptor.GetProvider(typeof(EmployeeModel)))

        {
        }

        public MyTypeDescriptionProvider(TypeDescriptionProvider parent)
            : base(parent)
        {
        }

        public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
        {
            if (td == null)
            {
                td = base.GetTypeDescriptor(objectType, instance);
                td = new MyCustomTypeDescriptor(td);
            }
            return td;
        }
    }
}

namespace WorkDesk_Library.Binding_Assist
{
    class MyCustomTypeDescriptor : CustomTypeDescriptor
    {

        public MyCustomTypeDescriptor(ICustomTypeDescriptor parent)
            : base(parent)
        {
        }

        public override PropertyDescriptorCollection GetProperties()
        {
            PropertyDescriptorCollection cols = base.GetProperties();

            PropertyDescriptor JobTitle = cols["JobTitle"];

            PropertyDescriptorCollection JobTitle_child = JobTitle.GetChildProperties();

            PropertyDescriptor[] array = new PropertyDescriptor[cols.Count + 2];

            cols.CopyTo(array, 0);

            array[cols.Count] = new SubPropertyDescriptor(JobTitle, JobTitle_child["Name"], "JobTitle_Name");

            array[cols.Count + 1] = new SubPropertyDescriptor(JobTitle, JobTitle_child["ID"], "JobTitle_ID");

            PropertyDescriptorCollection newcols = new PropertyDescriptorCollection(array);

            return newcols;
        }

    }
}


namespace WorkDesk_Library.Interfaces
{
    class SubPropertyDescriptor : PropertyDescriptor
    {


        private PropertyDescriptor _subPD;
        private PropertyDescriptor _parentPD;

        public SubPropertyDescriptor(PropertyDescriptor parentPD, PropertyDescriptor subPD, string pdname)
            : base(pdname, null)
        {
            _subPD = subPD;
            _parentPD = parentPD;
        }

        public override Type ComponentType
        {
            get { return _parentPD.ComponentType; }
        }

        public override bool IsReadOnly { get { return false; } }

        public override Type PropertyType
        {
            get { return _subPD.PropertyType; }
        }

        public override bool CanResetValue(object component)
        {
            return false;
        }

        public override object GetValue(object component)
        {
            return _subPD.GetValue(_parentPD.GetValue(component));
        }

        public override void ResetValue(object component)
        {
        }

        public override void SetValue(object component, object value)
        {
            _subPD.SetValue(_parentPD.GetValue(component), value);
            OnValueChanged(component, EventArgs.Empty);
        }

        public override bool ShouldSerializeValue(object component)
        {
            return true;
        }
    }
}

 public void CreateEmployeeTable()
        {
            EmployeeGridView.DataSource = globalEmployeeList;
            EmployeeGridView.Columns[0].HeaderText = "Employee ID";
            EmployeeGridView.Columns["ID"].DisplayIndex = 0;
            EmployeeGridView.Columns["ListView"].DisplayIndex = 1;
            EmployeeGridView.Columns["ListView"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            EmployeeGridView.Columns["Department"].DisplayIndex = 2;
            EmployeeGridView.Columns["JobTitle"].DisplayIndex = 3;
            EmployeeGridView.Columns["JobTitle"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            EmployeeGridView.Columns["Nickname"].Visible = false;
            EmployeeGridView.Columns["FirstName"].Visible = false;
            EmployeeGridView.Columns["LastName"].Visible = false;
            EmployeeGridView.Columns["HireDate"].Visible = false;
        }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...