Monotouch TouchUpInside does not work, TouchDown works - c#

I have seen some topics about this subject in Objective-C. I read a lot of them, spent 2 days on it on trying to find a solution and none of them worked for me. I am mainly coding in C#. Since my problem behaviour (fire only when leaving/re-enter button) and context (C#) is a bit different. So, I will try my chance by asking my question here.
I will try to keep it simple.
Here is a sample of code:
private UIButton _buttonTest;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
_buttonTest = new UIButton(new RectangleF(10, 70, 50, 50));
_buttonTest.SetTitle("0", UIControlState.Normal);
_buttonTest.TouchUpInside += HandleButtonTestTouchUpInside;
_buttonTest.BackgroundColor = UIColor.Red;
this.View.AddSubview(_buttonTest);
}
void HandleButtonTestTouchUpInside (object sender, EventArgs e)
{
string textNumber = _buttonTest.Title(UIControlState.Normal);
// Increment Number
_buttonTest.SetTitle((int.Parse(textNumber)+1).ToString(), UIControlState.Normal);
}
There is a button and the title text is set to "0".
When the user click on it, it increments the number (title) by 1.
This code usually works very well!
However, it does not work in some of my classes for some unknown reasons...
Here is the problem:
TouchUpInside does not fire. ... However, if I hold the button with a finger and keep holding the finger while leaving the button and then re-entering the button then release the button, then.... it will fire the TouchUpInside, .... so the finger need to leave and re-renter the button while holding the button to make the TouchUpInside fires. Usually, this code works very well.
Things Checked:
if I replace TouchUpInside by TouchDown, then TouchDown works.
'User Interaction Enabled' is set to True for all superviews.
All views frames (among the superviews) seem to be inside their superview frames.
I moved the _buttonTest around and I noticed that the _buttonTest TouchUpInside does not fire correctly in the View, the SuperView, the SuperSuperView.... but it fires correctly in the SuperSuperSuperView.
Any suggestion?

In the SuperSuperView, I had this tap gesture that was entering in conflict with the Button event.
// Tap Gesture
UITapGestureRecognizer tapPageGestureRecognizer = new UITapGestureRecognizer();
tapPageGestureRecognizer.AddTarget(this, new Selector ("HandleTapPageGestureRecognizer:"));
this.View.AddGestureRecognizer(tapPageGestureRecognizer);
The idea is to disable the gesture SuperSuperView gesture when the button event, TouchDown was fired, ... and to re-enable it when the TouchUpInside is fired.
So here is one solution for the problem:
private void SetGrandParentViewGestureEnabled(bool enabled)
{
foreach(UIGestureRecognizer g in this.View.Superview.Superview.GestureRecognizers)
{
g.Enabled = enabled;
}
}
void HandleButtonSubmitTouchDown (object sender, EventArgs e)
{
SetGrandParentViewGestureEnabled(false);
}
void HandleButtonSubmitTouchUpInside (object sender, EventArgs e)
{
// => Do treatments here!
SetGrandParentViewGestureEnabled(true);
}
However, I could have used EventHandler or Action to enable/disable the tap gesture.
EDIT: Here is another function that need to be added as well to re-enable the gesture.
void HandleButtonSubmitTouchUpOutside (object sender, EventArgs e)
{
SetGrandParentViewGestureEnabled(true);
}

I had a similar problem, I ended up using a tap recognizer together with the long press recognizer like this for the button TopRightButton.
var longPressGesture = new UILongPressGestureRecognizer(Action);
TopRightButton.AddGestureRecognizer(longPressGesture);
var tapRecognizer = new UITapGestureRecognizer();
tapRecognizer.AddTarget(() =>
{
//method
});
tapRecognizer.NumberOfTapsRequired = 1;
this.TopRightButton.AddGestureRecognizer(tapRecognizer);
private void Action(){ };

Related

Button mouse over ForeColour change

To create a mouse over button I use this code
private void btnCreateAccount_MouseHover(object sender, EventArgs e)
{
btnCreateAccount.ForeColor = Color.Gold;
}
private void btnCreateAccount_MouseLeave(object sender, EventArgs e)
{
btnCreateAccount.ForeColor = Color.Black;
}
The mouse over button works however when I hover over the button there is a good at least 1 second delay. I would think that it should change colour as soon as the mouse is placed over the button and not with a (in my opinion) too long delay.
Is there any way of fixing that code by like refreshing the button or something along those lines? or perhaps someone has a code that works perfectly?
You are handling the Mouse Hover event. This will require the cursor to be still for a short while in order to fire.
The pause required for this event to be raised is specified in milliseconds by the MouseHoverTime property.
This is read only.
Normally if you want the colour to change immediately you should handle the Mouse Enter event:
private void btnCreateAccount_MouseEnter(object sender, EventArgs e)
{
btnCreateAccount.ForeColor = Color.Gold;
}

React to Button.IsPressed WPF

I'd like to have a TextBlock changed when the button is pressed, and then return to the previous state when the button is released.
It appears that RepeatButton is not a solution here, as it only reacts to itself being held and not released - and I need to know when it is released so that I can run a proper method to return TextBlock to its original state. Being desperate I also tried to loop while(button.IsPressed) (yeah, I know, awful idea :() but to no avail - the code would hang (as if IsPressed did not change to false after the button had been released).
Is there any way to achieve it? Thanks in advance.
Maybe not the cleanest way, but I decided to create multiple handlers to my button: Click, PointerPressed, PointerCancelled, PointerCaptureLost, PointerReleased. First two are for handling the button being pressed, while the last three are for handling the release. I used all three due to recommendation here:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.uielement.pointerreleased
This is because PointerReleased may sometimes be substituded by other events being fired at button release.
PreviewMouseDown and PreviewMouseUp seem to work fine, if you want both left and right click to have your desired effect:
public partial class MainWindow : Window
{
private string TextBlockPreviousState = "";
public MainWindow()
{
InitializeComponent();
ButtonStatusTextBlock.Text = "foo";
}
private void StoreAndUpdate()
{
TextBlockPreviousState = ButtonStatusTextBlock.Text;
ButtonStatusTextBlock.Text = "Button Down";
}
private void Restore()
{
ButtonStatusTextBlock.Text = TextBlockPreviousState;
}
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
StoreAndUpdate();
}
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
Restore();
}
}

MouseHook, MouseDown and MouseClick split

I have a little problem. I tried to look at google, but it gave me nothing much.
I made a little program that uses global hooks and get mouse coordinates on click. The problem is when I made a second method with MouseDown and when I just click a button, MouseDown method runs too.
So the question is:
How can I split two methods and let them work only separately: when I click, only MouseClick method is triggered, when press and keep down for a while it triggers only MouseDown?
Should I use some timing or what? Just give me a tip what I should try to use.
P.S. Sorry, my English isn't good, it's not my native language.
Here is some code, that I think give the overview.
public void StartRecording()
{
mouseListener = new MouseHookListener(new GlobalHooker());
mouseListener.Start();
mouseListener.MouseClick += new MouseEventHandler(MouseClicked);
mouseListener.MouseDown += new MouseEventHandler(MouseDown);
}
public void MouseClicked(object sender, MouseEventArgs e)
{
MessageBox.Show(String.Format("Mouse was pressed at {0}, {1}",
Control.MousePosition.X.ToString(),
Control.MousePosition.Y.ToString()));
}
public void MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show(String.Format("Mouse was down at {0}, {1}",
Control.MousePosition.X.ToString(),
Control.MousePosition.Y.ToString()));
}
When you click the mouse both is the case.
MouseClick is as far as i know both MouseDown and MouseUp, where MouseDown will be fired when you press down. And MouseUp will be fired when you release the button..
I think you will have to add some functionality to the MouseDown method which counts how long the mouse was pressed down.. That would be my solution.
In the MouseDown event you should store the current time and coordinates in variables that are global to the class they are in.
Then, you should use the MouseUp event to detect when the mouse button is released. You can then compare the new time and coordinates to the stored ones to see how long the button was pressed and if the mouse moved in that time, and act upon it accordingly.
Alternatively, you could also use the MouseMove event to reset the time and coordinates if required.
As a workaround, instead of hooking to MouseClick, try using MouseUp.
Then on MouseDown save current time in a class level variable (clickTime in the example). On MouseUp check the time again. If the time span is longer then say 3 seconds - do what you wanted to do on mouse down, otherwise - continue with mouse click.
DateTime clickTime;
public void MouseUp(object sender, MouseEventArgs e)
{
if (DateTime.Now - clickTime > someDelayTime)
{
// Do mouse down
}
else
{
// Do mouse click
}
}
public void MouseDown(object sender, MouseEventArgs e)
{
clickTime = DateTime.Now;
}

How to determine if the camera button is half pressed

I am creating a small test camera application, and I would like to be able to implement a feature that allows focus text bars to be present on the screen while the hardware camera button is pressed half way down. I created a camera_ButtonHalfPress event to perform the focus action, but I am unsure of how to toggle the text bars I would like to show on the screen accordingly. Essentially, my goal would be to show the text bars while the camera button is pressed half way down, and then remove them if the button is pressed all the way or the button is released before being pressed all the way down. The button being released is the part I am having trouble with. What I have is as follows:
MainPage.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
...
//Event is fired when the button is half pressed
CameraButtons.ShutterKeyHalfPressed += camera_ButtonHalfPress;
//Event is fired when the button is fully pressed
CameraButtons.ShutterKeyPressed += camera_ButtonFullPress;
}
private void camera_ButtonHalfPress(object sender, EventArgs e)
{
//camera.Focus();
// Show the focus brackets.
focusBrackets.Visibility = Visibility.Visible;
}
}
private void camera_ButtonFullPress(object sender, EventArgs e)
{
// Hide the focus brackets.
focusBrackets.Visibility = Visibility.Collapsed;
camera.CaptureImage();
}
}
Currently, if the the user decides to release the camera button before it is pressed all the way, the focus brackets persist on the screen. How might I fix this issue?
If you add CameraButtons.ShutterKeyReleased to the OnNavigatedTo event, then the problem is solved!
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
...
CameraButtons.ShutterKeyReleased -= camera_ButtonReleased; //add corresponding event handler elsewhere
...
}
Just subscribe to the CameraButtons.ShutterKeyHalfPressed event of the camera, and hide the text bars inside.

How to simulate Left click in WPF from inside the event handler of right click

How to simulate Left click in WPF from inside the event handler of right click
Actually problem is the grid cell is not getting selected by directly right lcik on it.
If user first do a left click on grid cella nd then a right click then it works well.
So from inside the right click handler i want to first simulate the left click.
How to do this.
This is the right click event handler
void OnCFLgrdrightmouseclick(object sender, MouseButtonEventArgs e)
{
// usign the same sender and e i want to generate left click event first
// and then remaining code should execute
}
Something like, but you may have to guard for infinite recursion..
this.grid1 = ((System.Windows.Controls.Grid)(target));
this.grid1.MouseLeftButtonDown += new MouseButtonEventHandler(grid1_MouseLeftButtonDown);
this.grid1.MouseRightButtonDown += new MouseButtonEventHandler(grid1_MouseRightButtonDown);
void grid1_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if( leftClicked < (e.Timestamp - maxTimeBetweenClicks) )
{
MouseButtonEventArgs fakeLeftMouse = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.LeftButton);
grid1_MouseLeftButtonDown(sender, e);
}
leftClicked = 0;
throw new NotImplementedException();
}
void grid1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
leftClicked = e.Timestamp;
throw new NotImplementedException();
}
You shouldn't do it. It's a design flaw. Define rather actions that you want to execute when real events happen.
You can use MenuItemAutomationPeer for that:
MenuItemAutomationPeer peer = new MenuItemAutomationPeer(myMenuItem);
((IInvokeProvider)peer).Invoke();
EDIT:
But keep in mind that Bartosz Wójtowicz is right. You shouldn't use it in production code as it is not a good design. You can use it in testing code, so you won't have to change production code for testing purposes.

Categories

Resources