PropertyGrid альтернативы - PullRequest
       4

PropertyGrid альтернативы

7 голосов
/ 25 августа 2010

Мне нравится PropertyGrid, ну, по крайней мере, концепция, лежащая в его основе - используйте отражения и атрибуты для редактирования ваших объектов без написания большого количества кода пользовательского интерфейса.

Хотя мое волнение угасло довольно быстро, стандартная поставка PropertyGrid по умолчанию с WinFormsплоский отстой.Ну, это хорошо для редактирования простых объектов и тому подобного, но это еще не все.

  • Он не отображает соответствующие UITypeEditors для динамических свойств, имеющих тип "Object".
  • Как только ваши объекты содержат коллекции, вы можете редактировать их с помощью так называемого CollectionEditor.Тем не менее, он не будет запускать событие PropertyValueChanged.Поэтому, когда вам нужно добавить функциональность отмены, вы облажались.
  • И я до сих пор не нашел элегантного способа добавить проверку для CollectionEditor.
  • Реализовать отмену также проблематично, если вывыбрано несколько объектов, потому что в этом случае аргументы события PropertyValueChanged ChangedItem имеют значение null.

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

Что бы выделать?Есть ли элегантное решение хотя бы для первых трех вопросов?Есть ли альтернативная сетка свойств?Желательно бесплатно и без PInvokes?

Ответы [ 3 ]

5 голосов
/ 25 августа 2010

Большая часть элегантности PropertyGrid заключается в ее простоте. Помимо всего прочего, он предназначен для хорошей игры с Visual Studio, и я ожидаю увидеть его в основном в пользовательских UITypeEditor s и расширениях, а не в коде приложения.

Предположительно объекты, которые вы прикрепляете к PropertyGrid, являются классами вашего собственного дизайна? Я обнаружил, что для того, чтобы эффективно использовать сетку свойств, вы должны сильно украшать свои классы и членов с атрибутами.

Вы можете найти некоторую радость в написании собственных подклассов CollectionEditor (и других типов редакторов) и присоединении их к ученикам с помощью атрибута [Editor] - если вы можете прикрепить этот атрибут к своим динамическим свойствам, вы принудительное использование определенного редактора.

Единственный способ добавить валидацию к CollectionEditor - это переопределить метод CreateCollectionForm(), возвращая экземпляр вашего собственного пользовательского подкласса CollectionEditor.CollectionForm. Есть шанс, что вы сможете запускать события изменений отсюда.

К сожалению, все, что я могу сделать, это кивнуть и согласиться с утверждением об осуществлении отмены. Возможно, вам придется прибегнуть к «резервному копированию» затронутых объектов с помощью клонирования или сериализации для реализации отмены.

Я видел альтернативы встроенному элементу управления сеткой свойств, но они существуют в основном для предоставления различных визуальных стилей.

2 голосов
/ 20 сентября 2010

Если кому-то интересно - вот обходной путь для проблемы PropertyValueChanged, которая имитирует изменение, вызывая функцию MemberwiseClone в System.Object, если PropertyValueChanged из CollectionEditor был запущен ...

public class FixedCollectionEditor : CollectionEditor
{        
    bool modified;

    public FixedCollectionEditor(Type type)
        : base(type)
    { }

    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
    {            
        value = base.EditValue(context, provider, value);
        if (value != null && modified)
        {
            value = value.GetType()
                .GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic)
                .Invoke(value, new object[] { });                
        }
        modified = false;
        return value;
    }

    protected override CollectionForm CreateCollectionForm()
    {
        CollectionForm collectionForm = base.CreateCollectionForm();

        foreach (Control table in collectionForm.Controls)
        {
            if (!(table is TableLayoutPanel)) { continue; }
            foreach (Control c1 in table.Controls)
            {
                if (c1 is PropertyGrid)
                {
                    PropertyGrid propertyGrid = (PropertyGrid)c1;
                    propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(GotModifiedHandler);
                }
                if (c1 is TableLayoutPanel)
                {
                    foreach (Control c2 in c1.Controls)
                    {
                        if (!(c2 is Button)) { continue; }
                        Button button = (Button)c2;
                        if (button.Name == "addButton" || button.Name == "removeButton")
                        {
                            button.Click += new EventHandler(GotModifiedHandler);
                            if (button.ContextMenuStrip != null)
                            {
                                button.ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(GotModifiedHandler);
                            }
                        }
                    }
                }
            }
        }
        return collectionForm;
    }

    void GotModifiedHandler(object sender, EventArgs e)
    {
        modified = true;
    }
}
1 голос
/ 06 января 2011

Visualhint продает замену для сетки свойств, которая может помочь.Поскольку я никогда не использовал его в реальном проекте, я не знаю, насколько хорошо он работает.

...