Динамические свойства времени разработки C#

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

public class CustomButton : Control 
{
    private ButtonType _bType = ButtonType.OnOff;
    private Int32 _minPress = 50;   // 50 mS

    public ButtonType Button_Type
    {
        get { return _bType; }
        set { _bType = value; }
    }

    public Int32 Minimum_Press_Time // Only for momentary buttons
    {
        get { return _minPress; }
        set { _minPress = value; }
    }

}
public enum ButtonType 
{
    Momentary,
    OnOff
}

При добавлении CustomButton в форму Windows.Forms Minimum_Press_Time будет отображаться в окне свойств только в том случае, если Button_Type изменен на ButtonType.Momentary.

Возможно ли такое?


person frog_jr    schedule 16.04.2015    source источник
comment
Итак, во время разработки, как бы вы изменили свойство на Momentary через окно свойств? Что делать, если пользователь случайно изменил его и хочет изменить обратно? Похоже на плохой пользовательский опыт, если я что-то не упустил. Можете ли вы привести реальный сценарий?   -  person Rufus L    schedule 16.04.2015
comment
Чего я хочу. Если пользователь помещает кнопку в форму, а затем устанавливает для Button_Type значение Momentary, то свойство Minimum_Press_Time появляется в окне свойств и может быть установлено. Если затем пользователь устанавливает для Button_Type значение OnOff, свойство Minimum_Press_Time больше не отображается, хотя значение все еще находится в переменной класса. Я не думаю, что это возможно. Для моего реального класса у меня есть около 15 переменных, которые меняют свою допустимость в зависимости от выбранного типа. Похоже, мой выбор состоит в том, чтобы просто отображать все свойства (действительные или нет) или использовать несколько производных классов.   -  person frog_jr    schedule 16.04.2015


Ответы (1)


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

public partial class CustomButton : Control
{
    private ButtonType _buttonType = ButtonType.OnOff;
    private CustomButtonOptions _options = new OnOffButtonOptions();

    [RefreshProperties(System.ComponentModel.RefreshProperties.All)]
    public ButtonType ButtonType
    {
        get { return _buttonType; }
        set
        {
            switch (value)
            {
                case DynamicPropertiesTest.ButtonType.Momentary:
                    _options = new MomentaryButtonOptions();
                    break;
                default:
                    _options = new OnOffButtonOptions();
                    break;
            }
            _buttonType = value;
        }
    }

    [TypeConverter(typeof(ExpandableObjectConverter))]
    public CustomButtonOptions ButtonOptions
    {
        get { return _options; }
        set { _options = value; }
    }

    public CustomButton()
    {
        InitializeComponent();
    }
}

public enum ButtonType
{
    Momentary,
    OnOff
}

public abstract class CustomButtonOptions
{

}

public class MomentaryButtonOptions : CustomButtonOptions
{
    public int Minimum_Press_Time { get; set; }

    public override string ToString()
    {
        return Minimum_Press_Time.ToString();
    }
}

public class OnOffButtonOptions : CustomButtonOptions
{
    public override string ToString()
    {
        return "No Options";
    }
}

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

Это самый простой способ, который я нашел, чтобы максимально приблизиться к тому, о чем вы просите. Сетка свойств не всегда обновляется должным образом, поэтому иногда рядом с набором параметров без расширяемых свойств будет знак «+». Используйте «ToString» в свойствах, чтобы отображение в сетке свойств выглядело интеллектуальным.

person Ron Beyer    schedule 16.04.2015
comment
Я попробовал это, и это не совсем то, что я хотел, но это действительно то, что мне нужно, поэтому я отмечаю это как мой принятый ответ... Спасибо - person frog_jr; 17.04.2015
comment
Не углубляясь в попытки создания динамически компилируемых типов, это лучшее, на что вы можете надеяться. WPF справляется с этим намного лучше, чем WinForms. - person Ron Beyer; 18.04.2015