Как устранить ошибку времени разработки, когда элемент данных не найден с унаследованным источником привязки

Иногда полезно наследовать от базовой формы или базового пользовательского элемента управления, который предоставляет наследникам источник привязки.

Наследующие классы могут, например, установить источник данных для своего конкретного типа во время разработки или привязать элементы управления - и все это без написания специального кода в каждом унаследованном элементе управления для управления источником привязки. Вы даже можете использовать master-detail, добавив дочерние источники привязки с набором свойств элемента данных.

Дочерняя привязка отлично работает во время выполнения, но, к сожалению, дизайнер замечает это во время разработки при открытии сохраненного дочернего элемента управления. Вместо фактического выполнения кода в InitializeComponent конструктор использует десериализаторы для интерпретации текста. В этом случае источник привязки базового класса еще не настроен, когда дочерний класс пытается найти на нем член данных.

Короче говоря: идеальный код времени выполнения, но ошибка времени разработки «Элемент данных не найден в источнике данных».


person jnm2    schedule 03.02.2014    source источник


Ответы (1)


Одно из решений - создать подкласс BindingSource. Результирующий класс по-прежнему будет BindingSource, поэтому разработчик будет знать, что не следует помещать дополнительный источник привязки между ним и привязанным элементом управления.

Во время разработки любые дескрипторы свойств, которые дизайнер ожидает найти, будут созданы «на лету». Их не вспомнят. Дизайнер завершит инициализацию и откроется, и все будет так, как ожидалось.

Во время выполнения InheritableBindingSource ведет себя точно так же, как BindingSource.

public class InheritableBindingSource : BindingSource
{
    public override PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
    {
        if (this.DesignMode)
        {
            var baseProperties = base.GetItemProperties(listAccessors);
            var array = new PropertyDescriptor[baseProperties.Count];
            baseProperties.CopyTo(array, 0);
            // Return an identical class, but with a modified Find behaviour.
            return new DesignerPropertyDescriptorCollection(array);
        }

        // At runtime, InheritedBindingClass does nothing special.
        return base.GetItemProperties(listAccessors);
    }


    class DesignerPropertyDescriptorCollection : PropertyDescriptorCollection
    {
        public DesignerPropertyDescriptorCollection(PropertyDescriptor[] properties)
            : base(properties, readOnly: true)
        {
        }

        public override PropertyDescriptor Find(string name, bool ignoreCase)
        {
            // Guaranteed to return a descriptor for any property that is being looked up, whether it has any meaning or not.
            return base.Find(name, ignoreCase) ?? new DummyPropertyDescriptor(name);
        }
    }


    // A property descriptor that has no state whatsoever.
    class DummyPropertyDescriptor : PropertyDescriptor
    {
        public DummyPropertyDescriptor(string name)
            : base(name, new Attribute[0])
        {
        }

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

        public override Type ComponentType
        {
            get { return typeof(object); }
        }

        public override object GetValue(object component)
        {
            return null;
        }

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

        public override Type PropertyType
        {
            get { return typeof(object); }
        }

        public override void ResetValue(object component)
        {
        }

        public override void SetValue(object component, object value)
        {
        }

        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }
    }
}
person jnm2    schedule 03.02.2014