Abstract event

A

Andrus

public delegate void EntitySelectedEventHandler(EntityBase selectedEntity);

abstract internal partial class BrowseForm : Form {
public abstract event EntitySelectEventHandler EntitySelect { add;}
}

causes error: An add or remove accessor must have a body

but

public abstract EntitySelectedEventHandler EntitySelected { set; }

works OK.


Why events cannot be abstract ? How to create abstract events ?

Andrus.
 
J

Jeroen Mostert

Andrus said:
public delegate void EntitySelectedEventHandler(EntityBase selectedEntity);

abstract internal partial class BrowseForm : Form {
public abstract event EntitySelectEventHandler EntitySelect { add;}
}
An event can't have only an add-accessor, whether it's abstract or not. If
the event is not abstract, the compiler will auto-generate these for you,
which is why you usually don't declare them. You can do the following:

public abstract event EntitySelectEventHandler EntitySelect;

However, even that is not how it's usually done, since there is seldom a
point to forcing derived classes to implement the event themselves. This is
the usual pattern:

class A {
public event EntitySelectEventHandler EntitySelect;

protected virtual void OnEntitySelect(EntitySelectedEventArgs e) {
if (EntitySelect != null) EntitySelect(this, e);
}

// All internal event generators use the On... method instead of invoking
the event directly
}

class B : A {
public override void OnEntitySelect(EntitySelectedEventArgs e) {
// Custom processing before the attached event handlers fire
base.OnEntitySelect(e);
// Custom processing after the attached event handlers have fired
}
}

If you really want to, you can define the add and remove accessors to call
virtual methods as well, so the child classes can override them, but this is
rarely useful.
 
J

Jon Skeet [C# MVP]

Andrus said:
public delegate void EntitySelectedEventHandler(EntityBase selectedEntity);

abstract internal partial class BrowseForm : Form {
public abstract event EntitySelectEventHandler EntitySelect { add;}
}

causes error: An add or remove accessor must have a body

but

public abstract EntitySelectedEventHandler EntitySelected { set; }

works OK.


Why events cannot be abstract ? How to create abstract events ?

Events can be abstract, but you can't specify just the add part. An
event *always* has an add and a remove - you can't have one without the
other. Compare this with properties, where you can definitely have a
write-only or a read-only property.

Remove the "{ add; }" bit and it will compile okay.
 
A

Andrus

Jeroen,
However, even that is not how it's usually done, since there is seldom a
point to forcing derived classes to implement the event themselves. ....
If you really want to, you can define the add and remove accessors to call
virtual methods as well, so the child classes can override them, but this
is rarely useful.

I'm implementing winforms modeless picklist.
Picklist form contains picklist grid which raises EntitySelected event when
row is selected:

sealed class Grid<T> where T: EntityBase : BaseGrid {

internal event EntitySelectedEventHandler EntitySelected;

/// <summary>
/// Called when entity is selected by enter or by double click.
/// </summary>
/// <returns>true if event handler is present and event raised</returns>
bool OnEntitySelected() {
if (EntitySelected == null) return false;
T entityTmp = memoryCache.RetrieveElement(CurrentCell.RowIndex);
if (entityTmp == null)
// row has disappeared, some other user has changed data
return false;
EntitySelected(entityTmp);
return true;
}

Picklist form also implements EntitySelected event by forwarding it to
grid:

sealed class BrowseForm<T> where T: EntityBase : BrowseForm {
Grid<T> grid;

internal override event EntitySelectedEventHandler EntitySelect {
add {
grid.EntitySelected += value;
selectToolStripButton.Visible = true;
}

remove {
grid.EntitySelected -= value;
selectToolStripButton.Visible = false;
}
....

Combobox in main form invokes picklist form by using

class MyComboBox : ComboBox {

BrowseForm f;

protected override void OnDropDown(System.EventArgs e) {
f = new BrowseForm<Customer>();
f.EntitySelect += OnEntitySelected;
}

void OnEntitySelected(EntityBase selected) {
f.Close();
SelectedItem = selected;
Focus();
}

}

Questions:

1. Is this best design pattern for this ?

2. Picklist form sends selected event only to single form always, not to
multiple recipients for which event patter is designed. If main form is
closed before picklist form, event handler seems to be removed
automatically. So it is no need to implement remove. However event
implementation requires remove to be implemented.

Is it resonable to use delegate instead of event and implement only set
accessor ?

Andrus.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top