Как заставить CollectionEditor запускать событие CollectionChanged при добавлении или удалении элементов?

У меня есть этот пользовательский элемент управления, который я где-то давно взял:

public class NotifyingCollectionEditor : CollectionEditor
{
    // Define a static event to expose the inner PropertyGrid's PropertyValueChanged event args...
    public delegate void MyPropertyValueChangedEventHandler(object sender, PropertyValueChangedEventArgs e);
    public static event MyPropertyValueChangedEventHandler ElementChanged;

    // Inherit the default constructor from the standard Collection Editor...
    public NotifyingCollectionEditor(Type type) : base(type) { }

    // Override this method in order to access the containing user controls from the default Collection Editor form or to add new ones...
    protected override CollectionForm CreateCollectionForm()
    {
        // Getting the default layout of the Collection Editor...
        CollectionForm collectionForm = base.CreateCollectionForm();
        Form frmCollectionEditorForm = collectionForm as Form;
        TableLayoutPanel tlpLayout = frmCollectionEditorForm.Controls[0] as TableLayoutPanel;

        if (tlpLayout != null)
        {
            // Get a reference to the inner PropertyGrid and hook an event handler to it.
            if (tlpLayout.Controls[5] is PropertyGrid)
            {
                PropertyGrid propertyGrid = tlpLayout.Controls[5] as PropertyGrid;
                propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(propertyGrid_PropertyValueChanged);
            }
        }

        return collectionForm;
    }

    void propertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
    {
        // Fire our customized collection event...
        var evt = NotifyingCollectionEditor.ElementChanged;

        if (evt != null)
            evt(this, e);
    }
}

Раньше он запускал событие, когда один из редактируемых элементов в коллекции изменился, но мне нужно, чтобы он срабатывал, даже когда некоторые элементы были добавлены или удалены в эту коллекцию.

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

Но как я могу получить доступ к этой отредактированной коллекции, чтобы получить ее значение Count?

Я пытался получить доступ к propertyGrid.SelectedObject, но это null, и даже если бы это было не так, я думаю, что это элементы коллекции, а не коллекция.


person Kosmo零    schedule 16.10.2014    source источник


Ответы (2)


Лучше всего использовать ObservableCollection, определенную в System.Collections.ObjectModel. Это вызовет события, когда коллекция будет добавлена ​​или удалена. Этот класс является частью фреймворка и поэтому должен работать достаточно хорошо сейчас и в будущем.

Если вы хотите отслеживать тип в коллекции (T), то этот тип должен будет реализовать INotifyPropertyChanged.

person simon at rcl    schedule 16.10.2014

public class NotifyingCollectionEditor : CollectionEditor
{
    // Define a static event to expose the inner PropertyGrid's PropertyValueChanged event args...
    public static event EventHandler<PropertyValueChangedEventArgs> ElementChanged;

    // Inherit the default constructor from the standard Collection Editor...
    public NotifyingCollectionEditor(Type type) : base(type) { }

    // Override this method in order to access the containing user controls from the default Collection Editor form or to add new ones...
    protected override CollectionForm CreateCollectionForm()
    {
        // Getting the default layout of the Collection Editor...
        CollectionForm collectionForm = base.CreateCollectionForm();
        Form frmCollectionEditorForm = collectionForm as Form;
        TableLayoutPanel tlpLayout = frmCollectionEditorForm.Controls[0] as TableLayoutPanel;

        if (tlpLayout != null)
        {
            // Get a reference to the inner PropertyGrid and hook an event handler to it.
            if (tlpLayout.Controls[5] is PropertyGrid)
            {
                PropertyGrid propertyGrid = tlpLayout.Controls[5] as PropertyGrid;
                propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(propertyGrid_PropertyValueChanged);
            }
        }

        return collectionForm;
    }

    protected override object SetItems(object editValue, object[] value)
    {
        object ret_val = base.SetItems(editValue, value);

        // Fire our customized collection event...
        var evt = NotifyingCollectionEditor.ElementChanged;

        if (evt != null)
            evt(this, null);

        return ret_val;
    }

    void propertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
    {
        // Fire our customized collection event...
        var evt = NotifyingCollectionEditor.ElementChanged;

        if (evt != null)
            evt(this, e);
    }
}

Может сделать это.

person Kosmo零    schedule 20.10.2014