I try to use the UIPopoverPresentationController. For the presenting I need to assign the delegate (UIPopoverPresentationControllerDelegate) to be able to use methods like prepareForPopoverPresentation,
popoverPresentationControllerDidDismissPopover and so on.
If assign a view controller to the delegate property I get
Error CS0266 Cannot implicitly convert type 'UIKit.UIViewController' to 'UIKit.IUIPopoverPresentationControllerDelegate'. An explicit conversion exists (are you missing a cast?)
So what are my options here? In the native world one could add the required protocoll, but you can't do that in Xamarin. I want that the view controller which is presented in the popover gets the notification (prepare, did dismiss, ...). How can I do that?
Of course I could create a new instance of UIPopoverPresentationControllerDelegate and assign it, but then I would have connect the delegate with the view controller somehow (e.g. through events). Is there a simpler solution?
Edit
It looks like Xamarin has not exposed a WeakDelegate property and has also made the delegate class the abstract class for the protocol and not the interface. In this scenario - you will have to create another class that implements the UIPopoverPresentationControllerDelegate and another for the UIPopoverControllerDelegate.
In the future, it's worth noting that there is often a WeakDelegate property (along with Delegate) which allows assigning any class to the delegate and implementing the protocol implicitly through ExportAttribute on the protocol methods. Xamarin also sometimes uses the protocol's matching interface (such as IUIPopoverPresentationControllerDelegate) instead of the matching abstract class (the UIPopoverPresentationControllerDelegate class).
Mostly incorrect original answer
It should be possible for your UIViewController class to implement the IUIPopoverControllerDelegate and implement any methods that you need. Usually iOS protocols get converted into an interface for Xamarin.iOS and you can find it by appending an "I" to the protocol name.
public class TestVC : UIViewController, IUIPopoverControllerDelegate
{
public override UIPopoverPresentationController PopoverPresentationController {
get {
return base.PopoverPresentationController;
}
}
[Export ("popoverControllerDidDismissPopover:")]
public void DidDismiss (UIPopoverController popoverController)
{
throw new NotImplementedException ();
}
}
Here is an example where I've implemented a few of the popover methods. I hope this helps. I haven't explicitly tested this, but I think it should work. Let me know if it doesn't.
My solution was the following:
I subclassed UIPopoverPresentationControllerDelegate and here I defined the events PrepareForPopover and DidDismiss. So I overwrote PrepareForPopoverPresentation and DidDismissPopover and I throw the belonging events.
Then I assigned this delegate to my UIPopoverPresentationController instance. Through subscribing to the events of my custom delegate I was able to get notified, when the popover is displayed and when it is dismissed. Casting is not possible (as I tried in my question).
With this one can set some variables or call some methods from the view controller, which is presented in the popover.
Related
I'm using Xamarin to make an Android and iOS app. I have my code split into 3 projects: Android, iOS and common. The code is basically designed such that common code is abstract and handles the the OS agnostic side of things and the Android/iOS code inherits from the common and handles the OS specific things. However, I'm tripping over how to handle custom member variables following this paradigm, as I need to hold onto a OS specific instance so that the class can do OS things, but I also need to reference the OS specific instance in the common code to commonly handle things.
Example: A common class is comprised of a question and a chart (think public survey where you can see how other people responded). The common version of these things are responsible for retrieving their data from the appropriate places (database, server). The OS specific version of these things are responsible for displaying the UI. I would like to pass into this class the Android version of the question and chart. Then I can call the class' "retrieveData" (common) function and the class' "displayUi" (OS specific function). I would really like to reference the same member variables during this process.
If I program it 'normally', the common class would contain the common class of question and chart and the inherited Android class would access this variables. But this doesn't work because when the Android class access them, it gets the variables as common and doesn't have the OS specific functionality. If I put the variables in the Android class, then the base class doesn't know about them and I can't do common things with them.
Up to this point, I've gotten around this by using Generics. But I've recently ran into a problem with that solution (Inheriting generic can't up cast). Another solution I've thought of is using the 'new' operator on a property in the Android class to mask the inherited member variable and use the get function to automatically down cast the variable into the Android version and the set function to store the variable on the base (base.variable = value). I'm not too keen on this idea as I have to double declare the variables and I have a slight problem with collections of variables (I can either use Array.Convert (or some similar method) if I need to pass in the array/list/dictionary/etc, or I can cast as I iterate though it to do whatever it is I have to do. Not great, but doable.
I'm curious if there's other ways to to handle this situation .
Edit
Here's some simplified code:
public interface IAnsweredCommon { ... }
public interface IAnsweredAndroid : IAnsweredCommon { ... }
public abstract class ConstructorCommon<AnsweredType> where AnsweredType : IAnsweredCommon
{
protected AnsweredType Answered;
...
}
public class ConstructorAndroid : ConstructorCommon<IAnsweredAndroid> { ... }
As you can see, this version is using the generic pattern. ConstructorCommon has a variable of type AnsweredType which is treated as IAnsweredCommon within the class allowing it to do non-OS specific things with it. ConstructorAndroid inherits from ConstructorCommon using IAnsweredAndroid. This allows me to instantiate ConstructorAndroid without having to specify a type and allows it to treat the inherited AnsweredType as a IAnsweredAndroid to do OS specific things.
As mentioned in the previous question; this generic way won't work for an unrelated reason. So, to make code work in that question, I need away to replicate what the generic is doing. The only other way I can think of, is to change the Answered variable type from AnsweredType to IAnsweredCommon and to implement a new property in ConstructorAndroid that hides the Answered variable (via the 'new' keyword) and implement the get to return a casted base variable and set to set the base variable:
public abstract class ConstructorCommon
{
protected IAnsweredCommon Answered;
...
}
public class ConstructorAndroid : ConstructorCommon
{
protected new IAnsweredAndroid Answered
{
get => (IAnsweredAndroid)base.Answered;
set => base.Answered = value;
}
...
}
I'm not super crazy about this idea for the reasons I stated above, so I'm curious if there's another way.
I have written a COM-visible class library in C# 4.0 which I'm consuming with VB6. The thing works, only if I open up the VB6 object browser and look at the members exposed, I'm seeing an event for each and every single exposed member... but the C# code doesn't define any of them.
Is this normal? Am I doing something wrong?
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IMyClass))]
public class MyClass : IMyClass
{
public void DoSomething(string someParam)
{
...
}
}
public interface IMyClass
{
void DoSomething(string someParam);
}
The assembly is signed with a strong name key and AssemblyInfo.cs has the [assembly: ComVisible(true)] attribute set, but I'm not sure it has anything to do with the issue.
When I look at the object browser in VB6, I would be expecting to see DoSomething(string) as a member of MyClass, and I do, however I'm also seeing an event with a matching signature for every exposed method, like Event DoSomething(someParam As String) as a member of MyClass.
Even more puzzling (to me at least), properties also have a "matching" event (can only tell from the little lightning icon though) - if MyClass defined a property like this:
public string SomeProperty { get; set; }
The VB6 object browser would say the "event" is defined as Property SomeProperty As String, which leaves me flabbergasted - how does a "property" 1) gets duplicated and 2) the duplicate gets displayed with an "event" icon in the object browser? The same applies to get-only properties, which have their read-only "property/event" counterpart.
Where do these events come from and how do I get rid of them?
UPDATE An image is worth a thousand words:
UPDATE The wrong thing was the ComSourceInterfaces attribute which was mistakenly being used in place of a ComDefaultInterface attribute. Swapping the former for the latter gives the expected result:
By passing typeof(IMyClass) as an argument to the ComSourceInterface attribute you're saying that everything in the IMyClass is an event.
If you don't want an event interface for your class remove the ComSourceInterface attribute.
If you do want to expose events from your C# class to VB then do the following:
When you create a COM visible class you'll also want to create an interface that defines just the event handlers for your class. Your class should be decorated with the COMSourceInterface specifying your event handler interface and should define your events and implement the event handler interface. See How To: Raise Events Handled by a COM sink for another example.
[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface MyEvents
{
void ConnectedEvent(string state);
}
[ComSourceInterfaces(typeof(MyEvents))]
public class MyClass
{
public event Action<string> ConnectedEvent;
public MyClass() { }
public void DoSomething(string state)
{
if (ConnectedEvent != null)
ConnectedEvent(state);
}
}
See also: Murat's Corner: Exposing COM Events
You are basically finding out that there isn't anything special about events in COM. Like anything in COM, events are backed by an interface. The only thing special about an interface that specifies event methods is that it is marked with the [source] attribute in the type library. Which is all that the [ComSourceInterfaces] attribute does, recognized by Tlbexp.exe when it generates the type library.
Nor is there anything particularly special about properties in COM. They work just like they do in .NET, they are implemented with methods. A getter and a setter method.
So VB6 looks at your type library and is happy about a class that has events since it has an interface with the [source] attribute. And is happy about that interface having methods, all they can ever have, so it assumes those are the methods that run when the event is raised. It isn't otherwise smart enough to recognize that those methods are also the accessors for a property, it assumes that the type library author knows what he's doing.
Events are called "connection points" in COM. Google IConnectionPoint to learn more about it. If you ever create a WinRT component with custom event accessors then you'll also see that COM events have little in common with .NET events.
Anyhoo, the workaround is simple, only use [ComSourceInterface] when you raise events.
I am trying to learn OOP concept at an advance level. I was reading through the topic interfaces and have a confusion. But first, let me show you what exactly caused this confusion.
I tested this Code Sample. but I am confused with the use of interfaces. After implementing that code, it seems to me that I can call the method DoFirst from class A by simply creating an instance of it. so why use an interface at first place?
Something like this:
A myA = new A();
myA.DoFirst();
and similiarly,
B myB = new B();
myB.DoFirst();
In both the classes, i have to implement a method called 'DoFirst', so what good does interface provided to me?
Can't I just write these methods in different classes myself?
my Second question, say I have an interface that has 5 methods. If a class implements it, and only wants to provide implementation of 3 methods instead of writing code of all 5 methods supplied by the interface. Isn't this useless? why have access methods that i don't want?
can somebody answer these with example (Highly appreciated) please?
The advantage was already pointed out in the link you provided...
Basically you can also write
void DoSomething(IMyInterface obj)
{
obj.DoFirst();
}
And then send any type of object which implements that interface as a parameter.
A myA = new A();
DoSomething(myA);
B myB = new B();
DoSomething(myB);
The method DoSomethig doesn't care about the object's type, as long as it exposes an interface called IMyInterface.
Some Real Life examples - also, another way/reason to use interfaces.
In my own code I have an Engine which processes code to produce reports in Excel. In this engine, i had to write the code two different ways, one using the Microsoft Excel Interop, the other using the Open Office Interop. Rather than duplicate my entire engine to work two different ways, or write a lot of if statements in all the actual interop functions, I implemented an interface. Then I declared two classes, each one implementing the interface, but one uses Excel and the other uses open office. Then, in my code, I simple reference the interface and its functions and use a single if statement at the very beginning of the function to tell the interface which class to implement.
public class ExcelEngineInterop : ISSinterface
{ ... }
public class OOEngineInterop : ISSinterface
{ ... }
//cant use two variables with the same name, so use 1 interface reference instead
ISSinterface ssInt;
if(ExcelFlag)
ssInt = new ExcelEngineInterop();
else
ssInt = new OOEngineInterop();
//two VERY different functions between Excel and OpenOffice.
ssInt.OpenApp();
ssInt.OpenFile(fileName);
//etc etc and so on
This is the other reason to use an interface. When you need one block of code to act two (or more) different ways depending on some external flag.
Another Example.
There is a top level form with lots of custom user controls under it. The user fires a form level event, like a button click, but depending on which user controls are active and what settings are on them at the time the click happens, the controls themselves need to do something different. Rather than writing what could be a rediculously large number of if statements to make sure each one acts correctly from the top level, just implement an interface on each control, then do something like this:
public ButtonClick(object sender, EventArgs e)
{
//note: I dont know which of my classes currentrightcontrol belongs to at the moment.
// it could be any one of 22 different controls. It must be cast to something
// in order to call the ButtonClick method (its actual type is generic "UserControl"
IMyRunControl ctrl = CurrentRightControl as IMyRunControl;
ctrl.FormButtonClicked();
}
C# is a statically typed language (at least unless you explicitly tell it not to be). This means that the compiler uses the type of the variable to know whether the referenced object has the members you are about to use.
The interface, therefore, provides a contract to the compiler (and to other programmers, too) that this class implements that interface. Because interfaces can be shared across classes that don't have a hierarchical relationship, this means that you can define a method that can take an object as an argument by defining that interface in the parameter type.
I’m working on C# BHO plug-in for IE. Plug-in supposed to react on scroll event. Code bellow responsible for it:
var document = (HTMLDocument)webBrowser.Document;
((HTMLWindowEvents2_Event)document.parentWindow).onscroll += WebBrowserWindowOnScroll;
This approach works pretty good in IE7 and IE8. But completely useless in IE9.
I have found this workaround:
http://social.msdn.microsoft.com/Forums/et-EE/ieextensiondevelopment/thread/808df95a-c559-44c3-93b7-b9e3b2c3b737
It seems that it should solve problem but unfortunately it on C++ and I failed to move it on C#.
Can someone suggest workaround for IE9 or how to implement approach mentioned above on C#?
Thanks so much!
I managed to find the solution.
IHTMLWindow3 has a method attachEvent which requires name of the event as a first argument (“onscroll” in my case) and object which will be responsible for event handling. The trickiest part is connected with this handler object. It should implement IDispatch interface, but IE9 use this interface in a pretty bizarre way. It calls IDispatch.Invoke without specifying a method name which should be called. .NET automatically implements IDispatch when class marked by [ClassInterface(ClassInterfaceType.AutoDispatch)] attribute, and uses reflection to call its instance methods according to arguments of IDispatch.Invoke. In our case method name is empty so nothing will be called. [DispId(0)] attribute allows to solve this problem, it specifies method what should be called if Invoke receives empty method name.
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
public class EventListener
{
[DispId(0)]
public void HandleEvent(object target)
{
}
}
It should be mentioned that name of handler method doesn’t matter. But its signature is important. f.e. for ‘onscroll’ event it should be like shown above, ‘onclick’ handler requires no arguments etc.
I am wondering if there exists a built in class which provides a functionality similar to that of TypeDescriptor, except for method reflection rather than property.
I require this to dynamically create a context menu based on flagged methods within an object
e.g.
[ContextMenuItem(true)]
[DisplayName("Do Something")]
public override void DoSomthing()
{
...
}
I'm starting to build one myself as I haven't found one anywhere, but it always pays to ask :)
You could use the DescriptionAttribute and always look a for a particular string?
[Description("SPECIAL")]
void Doit(){}
But it's pretty easy to create your attribute type and then reflect for it, this way you can type your own parameters on to it.