2010-11-16 3 views
7

Мне нужно создать не визуальный компонент, FooComponent, который будет управлять некоторыми элементами управления типа Bar, который находится в его форме.Компонент .NET (невизуальный)

у меня есть следующие ограничения:

  1. FooComponent могут быть добавлены только к формам.
  2. Разрешается использовать только один FooComponent.
  3. FooComponent должен регистрироваться на событие закрытия формы и когда он срабатывает и выполняет какую-либо функцию на всех Bar и отправляет значение e.Cancel на основе возвращаемых значений.

# 1 и # 2 выше следует применять во время выполнения, а также время разработки. # 3 регистрация событий должна производиться автоматически, а не пользователями FooComponent.

Я искал Google и MSDN для получения некоторой помощи и читал о Component и ComponentDesigner классах, но я ничего не нашел для спасения.

Что мне делать?

+0

Я думаю, вы можете посмотреть CodeDomSerializer (http://msdn.microsoft.com/en-us/library/system.componentmodel.design.serialization.codedomserializer.aspx). Это может быть вашим лучшим выбором. – PHeiberg

+0

@PHeiberg: Спасибо –

ответ

3

(1) Чтобы контролировать, что компонент может быть добавлен только в форму, используйте конструктор FooComponent, которому передается форма, и не определяйте конструктор по умолчанию. Это называется:

FooComponent component = new FooComponent(this); 

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

FooComponent component = new FooComponent(); 

не компилируется.


(2) Выставьте FooComponent недвижимости на самой форме, так и в конструктор FooComponent, установить переданное формы FooComponent-х до this.


(3) То же самое, в конструкторе FooComponent, регистрироваться в случае закрытия для формы переданному


Положите все это вместе, и вы получите:

public class MyForm : Form { 
    public FooComponent OwnedComponent { get; set; } 
} 


public class FooComponent { 

    public FooComponent (MyForm OwnerForm) { 
     OwnerForm.OwnedComponent = this; 
     OwnerForm.FormClosing += MyCallback; 
    } 

    private void MyCallback(object sender, FormClosingEventArgs e) { 
     ... 
    } 

} 



EDIT
К сожалению, если вам нужно e default constructor, и если он должен быть истинным компонентом Drop-on-the-Form, нет никакого способа гарантировать, что компонент создается только в Форме или что у формы есть только один экземпляр компонента (не из внутри компонента, в любом случае).

Проблема двояка:
(1) Удаление компонента не добавляет компонент в форме, он добавляет его в components коллекции формы. Поэтому, даже если вы можете получить дескриптор родителя/владельца, он никогда не будет формой.

(2) Как отметил Нейл, отбрасывание компонента на форму вызывает конструктор по умолчанию, который не передает никаких параметров, и, конечно же, ни один из свойств компонента (например, сайт или контейнер) не заполняется.


Возможно полезно: Компонент может быть разработан, чтобы получить уведомление, когда он будет создан в несколько способов:

(1) Осуществляя конструктор, который принимает IContainer параметр. Когда компонент отбрасывается в форме, сгенерированный код будет вызывать этот конструктор. Тем не менее, он будет делать это только во время выполнения, а не во время разработки. Но контейнер будет ручкой для коллекции components формы.

public FooComponent(IContainer container) {...} 

(2) Внедрение ISupportInitialize. Когда компонент отбрасывается в форме, сгенерированный код дополнительно вызывает BeginInit() и EndInit(). В EndInit() вы можете получить доступ к таким областям, как Site и Container. Опять же, вы получите это только во время выполнения, а не в дизайне, а выброс исключения здесь не остановит создание компонента.

Старые, но отличные статьи по компонентам и элементам управления от MSDN Magazine от Майкла Вайнхардта и Криса Продает.
April 2003 Building Windows Forms Controls and Components with Rich Design-Time Features
May 2003 Building Windows Forms Controls and Components with Rich Design-Time Features, Part 2

Это теперь .chm файлы справки. Вам необходимо разблокировать страницу свойств файла, чтобы разрешить чтение содержимого после загрузки.

+0

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

+0

OP говорит, что это невизуальный компонент, который он создает, поэтому это не должно быть проблемой. Я имею в виду конструктор FooComponent конструктор ... Я уточню, что в вопросе –

+0

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

1

Я не думаю, что можно точно определить, что может содержать содержащийся класс. Я, конечно, никогда не видел экземпляр, где я получил ошибку (или даже предупреждение) для настройки свойства одного типа в другом, даже в WinForms.

Что-то, что вы, возможно, захотите сделать, это определить порожденного Формой предка для ваших форм, который содержит ссылку на ваш (внутренне видимый) FooComponent, инициализирует его при создании экземпляра и прикрепляет обработчики. Для достижения наилучших результатов он должен быть без параметров и единственной конструкторской перегрузкой, поэтому он формирует базу для любого конструктора, к которому приходят ваши потребители. Затем просто создайте домашнее правило, которое образуется из вашего класса предков, а не непосредственно из формы (вы можете использовать инструмент проверки кода, такой как FxCop, или аналогичный, чтобы обеспечить его выполнение, когда код привязан к исходному контролю). Теперь ваши пользователи получают FooComponent в каждой Форме, которую они создают, не могут создавать свои собственные (они являются внутренними и должны быть в другом проекте с вашим предком формы) и не должны делать ничего, кроме вывода из нового класса, чтобы заставить их формы вести себя как вы хотите.

+0

Мне нужно, чтобы это поддерживалось во время разработки, знаете ли вы, что для достижения № 3 во время разработки? –

1

Вы просите много. В целом, создание компонентов, знакомых с формой, которую они отбрасывают, довольно сложно. This answer может помочь вам реализовать обработчик событий. Вам нужно будет реализовать ISupportInitialize, чтобы получить вызов EndInit(), чтобы настроить обработчик событий.

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

Смежные вопросы