Окно свойств не отображает события для вложенных компонентов 3-го уровня, если только у вложенного компонента 2-го уровня нет события - PullRequest
3 голосов
/ 21 января 2020

У меня есть два System.ComponentModel класса, ComponentA и ComponentB:

public class ComponentA : Component
{
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ComponentB ComponentB { get; } = new ComponentB();

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Timer TimerA { get; } = new Timer();
}

public class ComponentB : Component
{
    //[Browsable(false)]
    public event EventHandler ComponentBEvent;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Timer TimerB { get; } = new Timer();
}

Обратите внимание, что у класса ComponentA есть свойство типа ComponentB, а у этого класса ComponentB есть свойство типа Timer (a система. Windows .Forms.Timer). У ComponentA также есть свойство типа Timer, хотя это еще не имеет значения. У ComponentB также есть событие (ComponentBEvent), этот факт является ключом к тому, что я обнаружил.

Таким образом, эти классы будут производить то, что я ищу, - это возможность назначать обработчики событий для событий во вложенных компонентах. с помощью окна свойств. На следующем снимке экрана вкладки «События» окна «Свойства» показано, как можно назначить обработчик события для события Tick свойства TimerB в ComponentB.

It is possible to assign event handlers to nested components by using the Properties Window

Исходный код для ComponentB выше, имеет закомментированный атрибут Browsable для события ComponentBEvent. Раскомментирование атрибута следующим образом:

public class ComponentB : Component
{
    [Browsable(false)]
    public event EventHandler ComponentBEvent;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Timer TimerB { get; } = new Timer();
}

приводит к нежелательному эффекту того, что ComponentB полностью исчезает на вкладке «События» окна «Свойства», делая невозможным назначение обработчика событий свойству TimerB компонента ComponentB.

When the containing component does not include an event then it disappears from the Events tab in the Properties Window

Итак, подведем итог. Я обнаружил, что можно использовать вкладку «Свойства» в окне «Свойства» для назначения обработчика событий для компонента, который имеет третий уровень Вложение (TimerB) требуется, чтобы содержащий компонент (ComponentB) имел событие (ComponentBEvent в примере). Это проблема только для компонентов с 3-м уровнем вложенности (или больше, я полагаю). Класс ComponentA не имеет никаких событий, но это не препятствует назначению обработчиков событий его свойству TimerA, как показано на первом снимке экрана.

Проблема, с которой я столкнулся, затрагивает только вкладку «События» окна «Свойства». На вкладке «Свойства» отображаются свойства всех компонентов, как и ожидалось.

The Properties tab of the Properties Window is unaffected

У меня вопрос: как использовать вкладку «Свойства» в окне «Свойства» для назначения обработчиков событий для компонента с 3-й уровень вложенности и не быть вынужденным иметь событие в содержащем его компоненте?

Мои тесты были выполнены с помощью приложения Windows Forms в. NET Framework 4.7.2 проекте.

Ответы [ 2 ]

0 голосов
/ 22 января 2020

Должно быть решение для решения проблемы, но я думаю, что оно не будет легким. Этот пост предлагает обходной путь, а не решение.

В дополнение к обходному пути, предложенному в другом ответе, я могу предложить два других обходных пути:

  1. Каждый компонент имеет Disposed событие, которое является допустимым событием, но оно не доступно для просмотра, вы можете сделать его доступным для просмотра (скрывая событие).
  2. Вы можете добавить фиктивное событие для просмотра, но только для чтения. Он будет отображаться в сетке свойств, но вы не можете назначить ему какой-либо обработчик событий.

Обходной путь 1 - Создание доступного события для компонента с возможностью просмотра

public class ComponentB : Component
{
    [Browsable(true)]
    public new event EventHandler Disposed
    {
        add { base.Disposed += value; }
        remove { base.Disposed -= value; }
    }

    // ... rest of properties ...
 }

Тогда будет показано так:

enter image description here

Обходной путь 2 - Создайте фиктивное событие, доступное только для чтения, с настраиваемым отображаемым именем

public class ComponentB : Component
{
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [ReadOnly(true)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    [DisplayName("Events")]
    [ParenthesizePropertyName(true)]
    public event EventHandler Dummy { add { } remove { } }

    // ... rest of properties ...
 }

Тогда оно будет показано так:

enter image description here

0 голосов
/ 21 января 2020

Если бы вы сами устанавливали PropertyGrid.SelectedObject, то я бы посоветовал вам в любом случае реализовать CustomTypeDescription ( пример ) для более ранней настройки возможности расширения его с помощью собственных атрибутов (это очень полезно) .

Но так как это окно свойств дизайнера winforms, я не знаю, как с этим справиться.

Хотя вы можете использовать обходной путь, выставляя отсутствующее событие на верхнем уровне:

public class ComponentA : Component
{
    public event EventHandler ComponentBTimerBTick
    {
        add => ComponentB.TimerB.Tick += value;
        remove => ComponentB.TimerB.Tick -= value;
    }

    ...
}
...