Hello i create a class which contains the event and the variables :
namespace FS
{
public class SomeEventArgs : EventArgs
{
public readonly string SomeVarible;
public SomeEventArgs (string someVarible)
{
SomeVarible= someVarible;
}
}
}
and i want to use this in another class :
namespace FS
{
delegate void Example(object sender, SomeEventArgs e);
public class OtherClass
{
public event Example example;
}
and i get this error :
Error CS7025 Inconsistent accessibility: event type 'Example' is less
accessible than event 'OtherClass.example'
You haven't specified access modifier of your delegate void Example(object sender, SomeEventArgs e); default one is internal, but event in class OtherClass is public.
It's illogical to expose something to other libraries with public modifier, while the underlying type is only accessible inside your library, because it is internal.
Easiest solution is making your delegate public, or your event public internal, depends how you want to use it.
You can find more about access modifiers here in documentation.
Related
I am trying to subscribe to an event that is in my base class but the method in my derived class doesn't seem to trigger whenever that event is triggered. Sample code is below.
public abstract class BaseClass
{
public delegate void EventHandler(object sender, EventArgs e);
public event EventHandler Event;
protected virtual void OnEvent(EventArgs ea)
{
if (this.Event!= null)
{
this.Event(null, ea);
}
}
}
public partial class DerivedClass : BaseClass
{
protected override void OnInit(EventArgs e)
{
base.Event+= DoSomething;
}
private void DoSomething(object sender, EventArgs e)
{
//Do Something here.
}
}
BaseClass.OnEvent is called in another control that has the same base class and the derived class where I want to subscribe to is inside another control. Is this possible?
BaseClass.OnEvent is called in another control that has the same base class and the derived class where I want to subscribe to is inside another control. Is this possible?
If you have a derived class and you have two instances of this derived class, the method of instance one won't be called if anything happens in instance two.
In your case you even have two different derived classes, sharing one base class and at runtime you have at least one instance of each derived class, which means, there is no communication between these two.
If you need to link two instances together you have to do something like this:
var instanceOne = new DerivedClassOne();
var instanceTwo = new DerivedClassTwo();
// When something in one happens, let two know:
instanceOne.OnEvent += (sender, e) => instanceTwo.ReactOnOtherChange();
I am working on a simple GUI framework, and I faced a problem calling protected virtual methods.
Here is the IKeyboardInputListenerService interface of service I use to receive keyboard events and the Control class that represents a base for all my GUI controls. The internal method is the one being refactored.
public interface IKeyboardInputListenerService
{
event EventHandler<KeyboardEventArgs> KeyPressed;
}
public abstract class Control
{
public IKeyboardInputListenerService KeyboardInputListenerService { get; }
protected Control(IKeyboardInputListenerService keyboardInputListenerService) =>
KeyboardInputListenerService = keyboardInputListenerService;
public event EventHandler<KeyboardEventArgs> KeyPressed;
/* protected */ internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{
if (enabled && visible && focused && !args.Suppressed)
{
KeyPressed?.Invoke(sender, args);
args.Suppressed = true;
}
}
public void Activate() =>
KeyboardInputListenerService.KeyPressed += new EventHandler<KeyboardEventArgs>(OnKeyPressed);
}
I also created a ContainerControl class that is supposed to contain child controls(like the Panel or GroupBox in Windows Forms) and that overrides the virtual method:
public abstract class ContainerControl : Control
{
private readonly ObservableCollection<Control> controls;
protected ContainerControl(IKeyboardInputListenerService keyboardInputListenerService)
: base(keyboardInputListenerService) =>
controls = new ObservableCollection<Control>();
/* protected */ internal override void OnKeyPressed(object sender, KeyboardEventArgs args)
{
foreach (Control control in controls)
control.OnKeyPressed(sender, args);
base.OnKeyPressed(sender, args);
}
}
Problem is, I cannot decide which modifier to use for methods such as OnKeyPressed. I wanted to make them protected, but it causes a compiler error:
Error CS1540 Cannot access protected member 'Control.OnKeyPressed(object, KeyboardEventArgs)' via a qualifier of type 'Control'; the qualifier must be of type 'ContainerControl' (or derived from it)
I can make them public, but I do not really think it is a good idea, because there is no reason for it except for resolving the problem caused by a cross-hierarchy call. I made them internal, but there is also a drawback: if anyone will want to create a user control, they will not be able to receive events, so the control will be useless.
The question is how to get access from a derived class to virtual methods of the base class without making the methods public-accessed.
Use protected internal
protected internal virtual void OnKeyPressed(object sender, KeyboardEventArgs args)
{ ... }
The documentation says:
protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly.
I have a DLL that needs to expose "event subscription" so a App that uses my DLL can subscribe to a specific event to get data. (The DLL itself subscribes to an event from a SDK)
I am pretty new to events, so please be gentle with me and explain.
I have a DLL that looks for example like this:
internal class BaseClass
{
}
internal Class DerivedClass : BaseClass, InterfaceClass
{
public event TrackingEventHandler NewTrackingEventObservations;
public delegate void TrackingEventHandler(Object sender, TrackingEventArgs e);
}
In my interface, I want to expose the delegate TrackingEventHandler.
Interface:
public interface InterfaceClass
{
event TrackingEventHandler NewTrackingEventObservations; // <- Error: TrackingEventHandler is less accessable then the field NewTrackingEventObservations
}
How can I fix this issue?
Thanks a lot!
The error you’re getting is because TrackingEventHandler is contained in a class that is internal (only accessible by files within the same assembly, see this link), but the interface you’re trying to expose is public. You can either make the containing class public, or define TrackingEventHandler outside of this class (it doesn’t need to be contained in a class definition).
Here’s an example of defining it outside of a class:
namespace someNamespace
{
public delegate void TrackingEventHandler(Object sender, TrackingEventArgs e);
internal Class BaseClass{ }
internal Class DerivedClass : BaseClass, InterfaceClass
{
public event TrackingEventHandler NewTrackingEventObservations;
}
}
Given:
public delegate void MyHandler(object sender, EventArgs<SomeArgs> e)
public interface MyInterface
{
event MyHandler TheEvent;
}
class MyClass:MyInterface
{
public event MyHandler TheEvent;
}
class TheProblemClass:FrameworkElement //, IPossibleInterface?
{
public MyClass Instance1{get;set;}
public MyClass Instance2{get;set;}
//You used an instance of MyClass, now you must handle Instance1.TheEvent
//You used another instance of MyClass, now you must handle must handle Instance2.TheEvent
//...for any instance of MyClass, MUST handle TheEvent
}
Ok, so I intend for other devs to create their own classes using instances of MyClass. Any way to enforce the scope that declares an instance of MyClass to also handle the event?
I have an abstract base class that subclasses the UserControl class with no XAML. When I create a class based on the base class everything works fine (compiles and executes). But when I add code to the base class to fire an event, it compiles but when run I get a 'The invocation of the constructor on type 'ExtendedDisplay.UserControls.Annotations' that matches the specified binding constraints threw an exception.' error. Not sure why.
Here is my code for the base class,
public abstract class BaseClass: UserControl
{
protected static System.Type ControlType;
public static readonly RoutedEvent RefreshEvent = EventManager.RegisterRoutedEvent(
"RefreshEvent",
RoutingStrategy.Bubble,
typeof(RefreshEventHandler),
ControlType);
public delegate void RefreshEventHandler(object sender, RefreshEventArgs e);
public event RefreshEventHandler RefreshNeeded
{
add { AddHandler(RefreshEvent, value); }
remove { RemoveHandler(RefreshEvent, value); }
}
protected void RaiseRefreshEvent(RoutedEventArgs e)
{
RaiseEvent(new RefreshEventArgs(RefreshEvent, this));
e.Handled = true;
}
public class RefreshEventArgs : RoutedEventArgs
{
public RefreshEventArgs(RoutedEvent routedEvent, object source)
: base(routedEvent, source) { }
}
}
This code works as expected when hardcoded into the UserControl. Any ideas/help would be greatly appreciated.
On further testing it appears that I can't replace the last parameter in the EventManager.RegisterRoutedEvent function with a variable. I have a variable "protected static System.Type ControlType;" that is set to the typeof control by the derived control. This doesn't work when hard coded either. To make it work, I can't use a variable, even though it is the right type. Is ther any way around this?
Ok,
Finally figured it out. What I did was to have the baseclass member "RefreshEvent" just declared in the baseclass and assigned in the derived class. This works great and does what I need keeping the bulk of the boilerplate in the baseclass.