At the moment I am using a example code from the internet, but I want to change it so I can get the value of the mousebutton that is pressed down as an string value to use further in the Form1.cs under a button.
The problem is I can't really get the return value from the mousebutton that is pressed down. It keeps giving me null values. Is this because its a anonymous async method? Im new to async and anonoymous methods, but read some information about this on the internet. Here is the code in the class I used. Also I used the MouseKeyHook NuGet package from George Mamaladze. I want to get the result to return or "save" somewhere so it stays as an constant. Now the result changes directly after the input of the mousebutton, because its probably a async method that runs on the background.
public class ClickDetector
{
public ClickDetector() { }
public static void ListenForMouseEvents()
{
Console.WriteLine("Listening to mouse clicks.");
//When a mouse button is pressed
Hook.GlobalEvents().MouseDown += async (sender, e) =>
{
Form1.label1.Text = $"Mouse {e.Button} Down"; //This should modify label1.Text.
var result = e.Button.ToString();
};
//When a double click is made
Hook.GlobalEvents().MouseDoubleClick += async (sender, e) =>
{
Form1.label1.Text = $"Mouse {e.Button} button double clicked."; //This should modify label1.Text.
};
}
}
Related
I'm new with Xamarin forms and don't know how to deal with this case. I've tryed to implement it in several ways but with no success.
I have a page where when user makes an action (write a text on a text box and send it with enter key) my app must make some checkings. Depending on the result of the checks, it could be necessary to show a modal page with a list of item to select. Ones user makes the selection process must continue with other checks. And here is my problem, because in this next checkings I have to show another page. User must make a selection/enter some date, and then continue to complete the proccess, but this page is not appear.
I'm using the messagingCenter to subscribe to the modal pages. First modal page appears and makes the selection well. Second modal page is never shown and then proccess never complets.
Here is some of my code:
NavigationPage navigationPage = new NavigationPage(new ListItemsPage(products));
Navigation.PushModalAsync(navigationPage);
MessagingCenter.Subscribe<ListItemsPage, Guid?>(this, "Select product", (obj, item) =>
{
try
{
if (item != null)
{
product = products.SingleOrDefault(x => x.Guid == item);
if (product != null) ProcessLine(product);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
MessagingCenter.Unsubscribe<ListItemsPage, Guid?>(this, "Select product");
}
});
On ListItemsPage I have this code whe item is selected:
private void MenuItem_Clicked(object sender, EventArgs e)
{
// some logic...
Navigation.PopModalAsync();
MessagingCenter.Send(this, "Select product", SelectedGuid);
}
SelectedGuid is a Guid type data and when debbugin is well selected.
Problems comes when goes to ProcessLine method.
private void ProcessLine(Product product) {
// make some logic...
NavigationPage navigationPage = new NavigationPage(new ControlUnitsPage(model));
Navigation.PushModalAsync(navigationPage);
MessagingCenter.Subscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", (obj, item) =>
{
try
{
if (item != null)
{
_date = item.Date;
_code = item.Code;
_units = item.Units;
Save(productLine, product, _units, _date,_code);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
MessagingCenter.Unsubscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code");
}
});
}
ControlUnitsPage has the same structure as the last one page. First makes a PopModalAsync and then sends the message sending an instance of ControlUnits type.
private void Button_Clicked(object sender, EventArgs e)
{
//some logic...
Item = new ControlUnits() { Date = DateField.Date, Code = CodeField.Text, Units = int.Parse(SelectedUnits.Value.ToString()) };
Navigation.PopModalAsync();
MessagingCenter.Send(this, "Select units, date and lot code", Item);
}
I think problem is in the order of invoking method but dont know what is the properly order because I am not able to understand how pushmodal, popmodal methods work, whether or not I should use await with it if after that comes a subscription. I really don't know and I need help, please.
Thank you so much!
your Send and Subscribe calls both need to use matching parameters
if Subscribe looks like this
MessagingCenter.Subscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", (obj, item) => ... );
then Send needs to match
MessagingCenter.Send<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", Item);
I have a Xamarin.Form MainPage:ContentPage with a ToolbarItems Bar on top. The toolbar items are bound to my ViewModel like so:
<ToolbarItem Text="Sync" Command="{Binding ReloadCommand}" >
</ToolbarItem>
The availability of the Item depends on some logic:
private bool canReloadExecute(object arg)
{
bool result = (!IsReloading && (App.GetPersistentSetting("DeviceID") != "") && (App.GetPersistentSetting("BuildingID") != ""));
return result;
}
There is a separate dialog controlling the DeviceID and BuildingID on a different settings page. Once any of those ids is entered it is persistently stored away
App.SetPersistentSetting("DeviceID",value);
Problem is, that the menu items don't change their appearance once my code uses popAsync() to return to the Main page. I need to restart my app to see the changes. According to the debugger, canReloadExecute isn't called. Why this?
What I tried to work around this issue is to force a refresh in the MainPage's OnAppearing method like this:
public void RefreshToolbarItems()
{
TestApp.ViewModels.MainViewModel mvm = (TestApp.ViewModels.MainViewModel)BindingContext;
mvm.RefreshToolbarItems();
}
... and in the ViewModel:
public void RefreshToolbarItems()
{
OnPropertyChanged("BuildingScanCommand");
OnPropertyChanged("ReloadCommand");
}
but this code runs through but changes nothing, while the Debugger shows that the routine is indeed firing the events, they seem to go nowhere.
Any ideas how I can get my menu going?
Edit 1: "Show command initalization"
I am not shre what specifically you mean, but here is the whole code dealing with the command:
private ICommand _reloadCommand;
public ICommand ReloadCommand => _reloadCommand ?? (_reloadCommand = new Command(ExecuteReloadCommand, canReloadExecute));
private bool _isReloading = false;
public bool IsReloading
{
get => _isReloading;
set
{
_isReloading = value;
((Command)_reloadCommand).ChangeCanExecute();
OnPropertyChanged(nameof(ReloadCommand));
}
}
private bool canReloadExecute(object arg)
{
bool result = (!IsReloading && (App.GetPersistentSetting("DeviceID") != "") && (App.GetPersistentSetting("BuildingID") != ""));
return result;
}
private async void ExecuteReloadCommand(object obj)
{
IsReloading = true;
// Some code ...
IsReloading = false;
}
The goal is to disable the command, if either the command handler is already running, or if the configuration of DeviceID and/or BuildingId hasn't been done yet.
The enable/disable does almost work, if I set the DeviceId and BuildingId, and restart the app, the command is properly enabled or disabled. It doesn't work, however, if I set the Ids in a sub-page and return to the main page.
meanwhile I came to the conclusion, that firing onPropertyChange obviously doesn't make the command check its canReloadExecute. So the question is, how do I trigger this?
I finally solved the issue myself, this code works nicely for me:
public void RefreshToolbarItems()
{
((Command)BuildingScanCommand).ChangeCanExecute();
((Command)ReloadCommand).ChangeCanExecute();
}
In my app, I have a searchbox which allows users to filter as they type. For some reason I can't get an InfinteProgress to properly display while the filtering is being executed.
Here's my code:
Pass 1
public void renderForumList(){
try{
magnify = mStateMachine.findForumSearchIcon(form);
}catch(NullPointerException ex){
System.out.println("User typed additional character in search term before previous term finished executing");
}
InfiniteProgress infi = new InfiniteProgress();
magnify.getParent().replace(magnify, infi, null);
Display.getInstance().invokeAndBlock(new Runnable() {
#Override
public void run() {
for (int i = 0;i < containerStates.length;i++){
if(containerStates[i] != listItems[i].isVisible()){
listItems[i].setHidden(!containerStates[i]);
listItems[i].setVisible(containerStates[i]);
}
}
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
mStateMachine.findForumsListComponent(form).animateLayout(200);
mStateMachine.findContainer2(form).replace(infi, magnify, null);
}
});
}
});
}
In this version, the infinite progress shows up in the proper position, but it doesn't spin.
Pass 2
public void renderForumList(){
try{
magnify = mStateMachine.findForumSearchIcon(form);
}catch(NullPointerException ex){
System.out.println("User typed additional character in search term before previous term finished executing");
}
InfiniteProgress infi = new InfiniteProgress();
magnify.getParent().replace(magnify, infi, null);
for (int i = 0;i < containerStates.length;i++){
if(containerStates[i] != listItems[i].isVisible()){
listItems[i].setHidden(!containerStates[i]);
listItems[i].setVisible(containerStates[i]);
}
}
mStateMachine.findForumsListComponent(form).animateLayout(200);
mStateMachine.findContainer2(form).replace(infi, magnify, null);
}
}
}
In this version, the magnifier icon just flashes briefly, but the InfiniteProgress spinner is never visible.
I get the same results on the simulator and on an Android device.
How can I get the InfiniteProgress to spin while the search is taking place?
invokeAndBlock opens a new thread and thus violates the EDT as you access UI components on a separate thread.
Try using callSerially instead to postpone the following code into the next EDT cycle although I'm not sure that will help as everything is still happening on the EDT.
Alternatively I'm guessing the method isVisible takes time, so you can enclose that call alone in invokeAndBlock.
To understand invokeAndBlock check out the developer guide https://www.codenameone.com/manual/edt.html
I'm implementing a DynamicItemStart button inside a Menu Controller. I'm loading the dynamic items for this button when Visual Studio starts. Everything is loaded correctly so the initialize method is called an I see all the new items in this Dynamic button. After the package is completely loaded I want to add more items to this Dynamic button, but since the package is already loaded the initialize method is not called again and I cannot see the new items in this Dynamic button. I only see the ones that were loaded when VS started.
Is there any way that I can force the update of this Dynamic button so it shows the new items?. I want to be able to update the VS UI after I added more items but outside the Initialize method.
The implementation I did is very similar to the one showed on this msdn example:
http://msdn.microsoft.com/en-us/library/bb166492.aspx
Does anyone know if an Update of the UI can be done by demand?
Any hints are greatly appreciated.
I finally got this working. The main thing is the implementation of a derived class of OleMenuCommand that implements a new constructor with a Predicate. This predicate is used to check if a new command is a match within the DynamicItemStart button.
public class DynamicItemMenuCommand : OleMenuCommand
{
private Predicate<int> matches;
public DynamicItemMenuCommand(CommandID rootId, Predicate<int> matches, EventHandler invokeHandler, EventHandler beforeQueryStatusHandler)
: base(invokeHandler, null, beforeQueryStatusHandler, rootId)
{
if (matches == null)
{
throw new ArgumentNullException("Matches predicate cannot be null.");
}
this.matches = matches;
}
public override bool DynamicItemMatch(int cmdId)
{
if (this.matches(cmdId))
{
this.MatchedCommandId = cmdId;
return true;
}
this.MatchedCommandId = 0;
return false;
}
}
The above class should be used when adding the commands on execution time. Here's the code that creates the commands
public class ListMenu
{
private int _baselistID = (int)PkgCmdIDList.cmdidMRUList;
private List<IVsDataExplorerConnection> _connectionsList;
public ListMenu(ref OleMenuCommandService mcs)
{
InitMRUMenu(ref mcs);
}
internal void InitMRUMenu(ref OleMenuCommandService mcs)
{
if (mcs != null)
{
//_baselistID has the guid value of the DynamicStartItem
CommandID dynamicItemRootId = new CommandID(GuidList.guidIDEToolbarCmdSet, _baselistID);
DynamicItemMenuCommand dynamicMenuCommand = new DynamicItemMenuCommand(dynamicItemRootId, isValidDynamicItem, OnInvokedDynamicItem, OnBeforeQueryStatusDynamicItem);
mcs.AddCommand(dynamicMenuCommand);
}
}
private bool IsValidDynamicItem(int commandId)
{
return ((commandId - _baselistID) < connectionsCount); // here is the place to put the criteria to add a new command to the dynamic button
}
private void OnInvokedDynamicItem(object sender, EventArgs args)
{
DynamicItemMenuCommand invokedCommand = (DynamicItemMenuCommand)sender;
if (null != invokedCommand)
{
.....
}
}
private void OnBeforeQueryStatusDynamicItem(object sender, EventArgs args)
{
DynamicItemMenuCommand matchedCommand = (DynamicItemMenuCommand)sender;
bool isRootItem = (matchedCommand.MatchedCommandId == 0);
matchedCommand.Enabled = true;
matchedCommand.Visible = true;
int indexForDisplay = (isRootItem ? 0 : (matchedCommand.MatchedCommandId - _baselistID));
matchedCommand.Text = "Text for the command";
matchedCommand.MatchedCommandId = 0;
}
}
I had to review a lot of documentation since it was not very clear how the commands can be added on execution time. So I hope this save some time whoever has to implement anything similar.
The missing piece for me was figuring out how to control the addition of new items.
It took me some time to figure out that the matches predicate (the IsValidDynamicItem method in the sample) controls how many items get added - as long as it returns true, the OnBeforeQueryStatusDynamicItem gets invoked and can set the details (Enabled/Visible/Checked/Text etc.) of the match to be added to the menu.
I need to execute Show created file name each time Watch files fires an event
WatchFilesActivity : NativeActivity
protected override void Execute(NativeActivityContext context)
{
var fileSystemWatcher = new FileSystemWatcher(context.GetValue(Path));
fileSystemWatcher.IncludeSubdirectories = context.GetValue(IncludeSubdirectories);
fileSystemWatcher.Filter = context.GetValue(Filter);
var bookmark = context.CreateBookmark(ResumeFileCreatedBookmark);
context.GetExtension<FileSystemWatcherExtension>().Start(fileSystemWatcher, bookmark);
}
Extension
public class FileSystemWatcherExtension : IWorkflowInstanceExtension
{
WorkflowInstanceProxy instance;
Bookmark bookmark;
public void SetInstance(WorkflowInstanceProxy instance)
{
this.instance = instance;
}
IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
{
yield break;
}
public void Start(FileSystemWatcher fileSystemWatcher, Bookmark bookmark)
{
this.bookmark = bookmark;
fileSystemWatcher.Created += new FileSystemEventHandler(FileCreated);
fileSystemWatcher.EnableRaisingEvents = true;
}
void FileCreated(object sender, FileSystemEventArgs e)//When the file arrives
{
instance.BeginResumeBookmark(bookmark, e.FullPath, CompleteResume, null);
}
void CompleteResume(IAsyncResult ar)
{
var result = instance.EndResumeBookmark(ar);
}
}
This is working great, but only once, and after this the host closes.
I can't put a WhileActivity because I need to handle consecutive very fast file creations and the processing time of an incoming file(Show created file name, in this case) is greater than the file creation rate
Thanks!
For a starter I would make the Show created file name activity a child activity of the Watch files activity so it can control it's execution. Next I would add a bookmark resumption callback so Watch files activity can react to and schedule the Show created file name activity in the callback.
Optionally you might want to create your bookmark with BookmarkOptions.MultipleResume so you can handle as many file events as you want and only move on when you want to do so.
public class WatchFilesActivity : NativeActivity
{
public Activity Child {get; set;}
protected override void Execute(NativeActivityContext context)
{
var fileSystemWatcher = new FileSystemWatcher(context.GetValue(Path));
fileSystemWatcher.IncludeSubdirectories = context.GetValue(IncludeSubdirectories);
fileSystemWatcher.Filter = context.GetValue(Filter);
var bookmark = context.CreateBookmark(ResumeFileCreatedBookmark, OnFileCreated, BookmarkOptions.MultipleResume);
context.GetExtension<FileSystemWatcherExtension>().Start(fileSystemWatcher, bookmark);
}
protected void OnFileCreated(NativeActivityContext context, Bookmark bookmark, object value)
{
var fileName = (string)value
context.ScheduleActivity(Child);
}
}
Note: Code typed in Notepad so possible typos.
If you need to pass the file name on to the child activity you can use an ActivityAction to do just that. See here for an example using an ActivityFunc which is just like an ActivityAction except it also has a return value.