WinRT event not returning EventRegistrationToken - c#

I am hoping someone can help me this problem... or can clarify what I am doing wrong...
I am dynamically adding event handlers to an event.
This works very well for Controls that comes with XAML, but not for my own events. I found out that in WinRT events returns a EventRegistrationToken. According to this link "add" should return a token.
My problem is that all events that I implement only returns void.
I created multiple projects (Win 8 WinRT, Win 8.1 Universal, Win 10 Universal) already to find out what I am doing wrong. Every project are showing the same problem. I googled hours... and every implementation I found are stating that "add" requires a return object.
My questions are:
Do someone know if this is a bug?
If not a bug... Is there something I have to set or change so that my events are returning a token?
If events are behaving like they should on your environment, can you please provide me with a test project so that I can so a compare. Maybe this has something to do with project settings or type.
edit: finally I can add an image...
PS: I also posted my code for the dynamic event handling on pastebin (code of DynamicEventHandler)

In your code,
var method = this.GetType().GetRuntimeMethods().First(x => x.Name == "ExecuteCommand")
The ExecuteCommand is a .NET method rather than the Windows Runtime method, why do you use "GetRuntimeMethods"?
Here is the code works on my side.
public MainPage()
{
this.InitializeComponent();
var runtimeEvent = this.myButton.GetType().GetRuntimeEvent("Click");
var handlerMethodInfo = this.GetType().GetMethod("OnClick");
var delegateHandler = handlerMethodInfo.CreateDelegate(runtimeEvent.EventHandlerType, this);
Func<Delegate, EventRegistrationToken> add = (a) => {
return (EventRegistrationToken)runtimeEvent.AddMethod.Invoke(this.myButton, new object[] { a });
};
Action<EventRegistrationToken> remove = (a) => { runtimeEvent.RemoveMethod.Invoke(runtimeEvent, new object[] { a }); };
WindowsRuntimeMarshal.AddEventHandler(add, remove, delegateHandler);
}
public void OnClick(Object sender, RoutedEventArgs e)
{
}

Related

How do I raise an external event in the Revit API from a WPF app?

I have been trying to create a Revit plugin that allows the user to view issues that are stored on a remote server on the local version of the file. It should create a new 3D perspective view from the stored data on the server and open it in Revit. However, whenever I attempt to run it, I get an exception warning thusly:
Exception thrown: 'Autodesk.Revit.Exceptions.InvalidOperationException' in RevitAPIUI.dll
An unhandled exception of type 'Autodesk.Revit.Exceptions.InvalidOperationException' occurred in RevitAPIUI.dll
Attempting to create an ExternalEvent outside of a standard API execution
I think I understand vaguely what this means, but I am unsure what exactly needs to be changed to fix it. I am defining a custom ExternalEventHandler and implementing its Execute method:
class CameraEventHandler : IExternalEventHandler
{
Issue issue;
int i;
public CameraEventHandler(Issue issue, int index)
{
this.issue = issue;
this.i = index;
}
public void Execute(UIApplication app)
{
Document doc = app.ActiveUIDocument.Document;
using (Transaction t = new Transaction(doc, "CameraTransaction"))
{
t.Start();
...
//Irrelevant code to set camera position programmatically
...
t.Commit();
}
}
public string GetName()
{
return "Camera event handler";
}
}
And then in one of my WPF forms, I create an ExternalEvent and calling the Raise method:
private void RevitViewButton_Click(object sender, RoutedEventArgs e)
{
CameraEventHandler handler = new CameraEventHandler(issue, issueIndex);
ExternalEvent cameraEvent = ExternalEvent.Create(handler);
cameraEvent.Raise();
}
However, the exception is thrown when it reaches the ExternalEvent.Create method.
Edit: I feel it is worth mentioning that the WPF app I am using is launched as a Revit plugin.
The Revit API cannot be used outside a valid Revit API context:
Use of the Revit API Requires a Valid Context
Revit API Context Summary
That is not a bug, Gaz, it is by design.
The solution suggested by Gaz is absolutely correct!
Reading this blog it would appear to be a bug in Revit.
The solution appears to be to create your custom handler during IExternalCommand.Execute or IExternalApplication.OnStartup, rather than at the time of raising the event.

Capture x and y of user touch, iOS Xamarin Forms

I am using Xamarin Forms (Xamarin Studio Community) to write an iOS app. I just need to capture the coordinates of user touch and release on a button.
I have searched all over Google, and I only found responses that simply did not work. They were either for Android, or Swift, or XCode, or WAY too much to make practical use of.
The closest I've seen are answers that say "There is currently no way to do that in Xamarin Forms." Which seems absurd to me because it seems like one of the most basic, fundamental things a programmer would need.
All I need is to capture the x,y from where the user touches and releases. Here are my handlers all ready to go.
thisHereButton.TouchDown += (object sender, System.EventArgs e) =>
{
//pressed
touchX = [x];
touchY=[y];
};
thisHereButton.TouchUpInside += (object sender, System.EventArgs e) =>
{
//released
releaseX = [x];
releaseY=[y];
};
That's it. If someone could provide a simple, practical answer, that would be great!
EDIT: With a bounty goes additional research, in hopes that someone can help.
I followed the advice in the comments and after some analysis, have determined that this is the chunk of code that is most relevant.
private bool touchStartedInside;
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
base.TouchesMoved(touches, evt);
// get the touch
UITouch touch = touches.AnyObject as UITouch;
if (touch != null)
{
//==== IMAGE TOUCH
if (backdrop.Frame.Contains(touch.LocationInView(View)))
{
//TouchStatus.Text = "Touches Moved";
}
//==== IMAGE DRAG
// check to see if the touch started in the drag me image
if (touchStartedInside)
{
// move the shape
float offsetX = (float)(touch.PreviousLocationInView(View).X - touch.LocationInView(View).X);
float offsetY = (float)(touch.PreviousLocationInView(View).Y - touch.LocationInView(View).Y);
txt_sizeValText.Text = "" + offsetY;
//DragImage.Frame = new RectangleF(new PointF(DragImage.Frame.X - offsetX, DragImage.Frame.Y - offsetY), DragImage.Frame.Size);
}
}
}
That is taken directly from their example. Right there in the code, it gives me what I'm looking for, as well as the bonus of the "offset" which is what I really need in the end.
So I've got this void in my code and the code still compiles, so there are no errors.
The only thing I cannot figure out is how to make use of this void. How do you call it?
If I have to use a different handler than the ones in my original post, that's fine. Whatever you can tell me about how to make this work...
You don't need to call the TouchesMoved() method. It is automatically called when the Objective C runtime calls it ( it is an override of the method to be called) - It is basically the handler of the native event. You can already get the offsets, and you can raise your own events inside that method to change your button. It is already done.

mvvmlight messenger strange behaviour

I have a strange behavior in my project. I use MvvmLight messenger to notify different parts of my UI to update.
public EntryViewModel(MenuViewModel menuVM, Entry item)
{
this._menuVM = menuVM;
OpenDetailsCommand = new RelayCommand(OpenDetailsInMainWindow);
BackCommand = new RelayCommand(Back);
this._entry = item;
Refresh();
Messenger.Default.Register<CardUpdateMessage>(this, this._entry.Id, msg => Refresh(); );
}
and send with
Messenger.Default.Send(new CardUpdateMessage(id), id);
when I see Messenger content after registration it contains about 400 registered actions of CardUpdateMessage, but when I call send none of them fires.
By the way, similar code with single registered object per Message type work as I expect. What is the cause of this problem?
Update: I have made some research with debugger and found that in file https://mvvmlight.codeplex.com/SourceControl/latest#GalaSoft.MvvmLight/GalaSoft.MvvmLight (PCL)/Messaging/Messenger.cs method SendToList is fired and in its inner loop WeakAction is fired, but Refresh method is not run. Does it something I haven't suspected with WeakAction?
Solution: I have found the case of this issue. It's NOT ALLOWED to use anonimous function in Messenger.Register due to unexpected behavior.
just Messenger.Default.Register(this, this._entry.Id, Refresh); and
private void Refresh(CardUpdateMessage msg) ...
External reference: https://mvvmlight.codeplex.com/workitem/7640
This is the answer https://mvvmlight.codeplex.com/workitem/7640 and this
Strange behavior with actions, local variables and garbage collection in MVVM light Messenger
Solution in short words - do no use lambdas in Messenger.Default.Register, because the can behave not as you expected.

Windows Phone 8.1 App crashes on ShowShareUI()

I'm trying to add share functionality to my Windows Phone App. The code behaves in an unpredictable way. Sometimes it works, but mostly it doesn't and I haven't been able to get any details about what's causing the crash. Could someone please go through the code below and let me know if I've missed something? Thanks!
public ArticlePage()
{
this.InitializeComponent();
//..
RegisterForShare();
}
private void RegisterForShare()
{
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager,
DataRequestedEventArgs>(this.ShareLinkHandler);
}
private void ShareLinkHandler(DataTransferManager sender, DataRequestedEventArgs e)
{
DataRequest request = e.Request;
DataRequestDeferral defferal = request.GetDeferral();
request.Data.Properties.Title = this.article.Title;
request.Data.Properties.Description = this.article.Summary;
request.Data.SetWebLink(new Uri(this.article.UrlDomain));
defferal.Complete();
}
private void ShareCommand_Click(object sender, RoutedEventArgs e)
{
DataTransferManager.ShowShareUI();
}
UPDATE
The code always works while I'm debugging from visual studio but pretty much never otherwise. I made a release build thinking there might be some code in the debug build which is causing the problem but that didn't make any difference.
I also had that problem recently. The share UI crashes when one of the important parameters is not set. In your case I'd suspect that
this.article.UrlDomain
is null or not a valid Uri pattern. You should build an if-clause around it and make sure that you're dealing with a real Uri. To test your code you should insert hardcoded constants and run it again. If it doesn't crash, check your Title, Summary and UrlDomain one by one.
Other places to investigate:
Try adding your handler in the OnNavigatedTo method and remove it when you're leaving the page
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested += SharePage_DataRequested;
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
DataTransferManager.GetForCurrentView().DataRequested -= SharePage_DataRequested;
}
I also searched my code and looked at official samples again and did not find any defferals. Just to be sure - if I were you I'd strip all unnessecary lines in my code and get it as closest as possible to the official examples and then extend it back to where it was from there which is why I would comment out these two lines as well:
void SharePage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
DataRequest request = e.Request;
//DataRequestDeferral defferal = request.GetDeferral();
request.Data.Properties.Title = this.article.Title;
request.Data.Properties.Description = this.article.Summary;
request.Data.SetWebLink(new Uri(this.article.UrlDomain));
//defferal.Complete();
}
Okay, I had the same problem. ShowShareUi actually suspends your app. If you try suspending your app you would get the error. It is actually the serialization problem.
If you want to look into the error, then while debugging, press the lifecycle events and suspend, you will crash in debug mode now.
If you are navigating between pages with a custom class you would get error. *My suggestion is that you would convert to jsonstring and send and get it back.*
I've faced similar problem (crash on ShowShareUI).
After very long investigations I've found, that this appears because unhandled exception in SaveFrameNavigationState (SuspensionManager class from template project).
In my case it was because SessionStateForFrame method failed on parsing class that couldn't be serialized.
Check out what you're saving in page state on SaveState of the page.
It happens not only on ShowShareUI but in suspend mode generally.

Is there a publicly accessible event to mark a ModalDialog close?

I recently made a custom ribbon in Sitecore. The two buttons in it fire off a command which activate a Xaml application using SheerResponse.ShowModalDialog. These applications effect the state of a database being read by another component on the ribbon.
I either need to be able to fire a custom event or function from the Xaml application to make the other ribbon component, or I need to be able to make the component on the ribbon aware that it needs to re-render when the ModalDialogs close. I don't see any obvious events which would do this, and I've gone about as far as I can when looking through the raw code with DotPeek and I haven't seen anything which even looks promising.
Apparently, the answer was there the whole time and I had missed it.
SheerResponse has a five parameter version of ShowModalDialog which accepts a boolean as a final parameter. This means I can couple it with ClientPage.Start:
Context.ClientPage.Start(this, "Run", kv);
}
private void Run(ClientPipelineArgs args)
{
var id = args.Parameters["id"];
if(!args.IsPostBack)
{
string controlUrl = string.Format("{0}&id={1}", UIUtil.GetUri("control:AltDelete"), id);
SheerResponse.ShowModalDialog(controlUrl,"","","",true);
args.WaitForPostBack();
}
else
{
Logger.LogDebug("post back");
}
Logger.LogDebug("out of if");
}

Categories