I launch a page on UWP thanks to PageRenderer, this page allows take picture and I want go back when user take a pciture.
My problem is when I go back with hardware button I have no problem but with function goback doesn't work.
This is my code :
var frame = Window.Current.Content as Frame;
if (frame != null && frame.CanGoBack)
{
frame.GoBack();
}
CanGoBack return false.
So you have some idea
Thanks
You need to hook into the back button pressed and then force the navigation back
public PageContainer()
{
this.InitializeComponent();
SystemNavigationManager.GetForCurrentView().BackRequested += PageContainer_BackRequested;
}
/// <summary>
/// Handles when the user presses the back button
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PageContainer_BackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null){
return;
}
// Navigate back if possible, and if the event has not
// already been handled .
if (rootFrame.CanGoBack && e.Handled == false)
{
e.Handled = true;
rootFrame.GoBack();
}
}
This example is an adaptation of the example provided on the MSDN website
You have to use the BackPressed Event.
public Test()
{
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}
private void Test_BackPressed(object sender, BackPressedEventArgs e)
{
if (this.Layer.CanGoBack)
{
e.Handled = true;
this.Layer.GoBack();
}
}
Related
So, as the subject says...what is the easiest way to hide FormRegion if email is in Reply mode whether its in a new window or with InlineResponse?
Just set the FormRegion.Visible property which returns a Boolean value that indicates whether the form region is visible or hidden.
Went back to test the approach in my answer after the question from #EugeneAstafiev and -- of course -- this was more complicated than I first thought... but I did get it working with some additional code.
The issue is that when the user clicks "Reply", it opens a new inspector window with a new instance of the FormRegion. So setting the Visible property to false in the event handler sets it only on the current "Read" mode inspector window -- rather than the new "Compose" mode inspector window that gets opened. So, instead the code samples below set up a bool flag property in ThisAddIn called LoadFormRegion that can be toggled to "false" when the Reply or ReplyAll event is fired.
Also, I noticed that setting Visible to false on the FormRegion still draws the area of the FormRegion on the inspector window, just with nothing in it. To completely prevent the FormRegion from loading, you can test for "Compose" mode and then the ThisAddin.LoadFormRegion flag in the FormRegionInitializing event handler located inside of the "Form Region Factory" at the top of the code page -- which is usually folded away from view. In that code block, setting "e.Cancel = true" will prevent the FormRegion from loading at all.
Here is the revised code for the FormRegion, which now subscribes to all three email button click events (Reply, ReplyAll, Forward), and sets the ThisAddIn.LoadFormRegion flag accordingly:
namespace TESTINGOutlookAddInVSTO
{
partial class FormRegion1
{
#region Form Region Factory
[Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Note)]
[Microsoft.Office.Tools.Outlook.FormRegionName("TESTINGOutlookAddInVSTO.FormRegion1")]
public partial class FormRegion1Factory
{
// Occurs before the form region is initialized.
// To prevent the form region from appearing, set e.Cancel to true.
// Use e.OutlookItem to get a reference to the current Outlook item.
private void FormRegion1Factory_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
{
if (e.FormRegionMode == Outlook.OlFormRegionMode.olFormRegionCompose)
{
var myAddIn = Globals.ThisAddIn;
if (myAddIn.LoadFormRegion == false)
{
e.Cancel = true;
}
}
}
}
#endregion
// Occurs before the form region is displayed.
// Use this.OutlookItem to get a reference to the current Outlook item.
// Use this.OutlookFormRegion to get a reference to the form region.
private void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
// Reset ThisAddIn.LoadFormRegion flag to true (in case user starts
// composing email from scratch without clicking Reply, ReplyAll or Forward)
var myAddin = Globals.ThisAddIn;
myAddin.LoadFormRegion = true;
var myMailItem = this.OutlookItem as Outlook.MailItem;
// Track these events to set the ThisAddIn.FormRegionShowing flag
((Outlook.ItemEvents_10_Event)myMailItem).Reply += myMailItem_Reply;
((Outlook.ItemEvents_10_Event)myMailItem).ReplyAll += myMailItem_ReplyAll;
((Outlook.ItemEvents_10_Event)myMailItem).Forward += myMailItem_Forward;
}
// Sets FormRegionShowing flag on ThisAddin
private void SetFormRegionShowing(bool show)
{
var myAddIn = Globals.ThisAddIn;
myAddIn.LoadFormRegion = show;
}
private void myMailItem_Forward(object Forward, ref bool Cancel)
{
SetFormRegionShowing(true);
}
private void myMailItem_ReplyAll(object Response, ref bool Cancel)
{
SetFormRegionShowing(false);
}
private void myMailItem_Reply(object Response, ref bool Cancel)
{
SetFormRegionShowing(false);
}
// Occurs when the form region is closed.
// Use this.OutlookItem to get a reference to the current Outlook item.
// Use this.OutlookFormRegion to get a reference to the form region.
private void FormRegion1_FormRegionClosed(object sender, System.EventArgs e)
{
}
}
}
And here's the new code for ThisAddIn to setup the LoadFormRegion property flag:
namespace TESTINGOutlookAddInVSTO
{
public partial class ThisAddIn
{
private bool loadFormRegion;
public bool LoadFormRegion { get => loadFormRegion; set => loadFormRegion = value; }
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
LoadFormRegion = true;
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// Note: Outlook no longer raises this event. If you have code that
// must run when Outlook shuts down, see https://go.microsoft.com/fwlink/?LinkId=506785
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
Tested the above and works nearly perfectly... I noticed that if there is a "Draft" reply in the user's Inbox created before the add-in was loaded, clicking on that email to continue editing in the Preview window or a new inspector window will cause some wonky display issues with the FormRegion. However, once I closed out that draft, then everything seemed to return to normal.
Could you please let me know how can I recognize long press gesture in Xamarin Forms application?
A few days before I used TapGestureRecognizer
TapGestureRecognizer imageTap = new TapGestureRecognizer();
imageTap.Tapped += (sender, args) => this.OnClickImage;
image.GestureRecognizers.Add(imageTap);
But I don't know how to make long press gesture according to this thread from xamarin forum
It should looks something like this, but it does not work.
var dumpParam = new RelayGesture((g, x) => DisplayAlert("Title", "Hello message", "Cancel"));
book.Cover.SetValue(Gestures.InterestsProperty, new GestureCollection() {
new GestureInterest
{
GestureType = GestureType.LongPress
GestureCommand = // what should I set?
GestureParameter = dumpParam
}
});
How to set my custom handler method?
You can do it cross platform way by attaching the below behavior, as long as it is Xamarin.Forms.Button or a sub-type of it.
using System;
using System.Threading;
using System.Windows.Input;
using Xamarin.Forms;
namespace App.Controls.Behaviors
{
public class LongPressBehavior : Behavior<Button>
{
private readonly object _syncObject = new object();
private const int Duration = 1000;
//timer to track long press
private Timer _timer;
//the timeout value for long press
private readonly int _duration;
//whether the button was released after press
private volatile bool _isReleased;
/// <summary>
/// Occurs when the associated button is long pressed.
/// </summary>
public event EventHandler LongPressed;
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command),
typeof(ICommand), typeof(LongPressBehavior), default(ICommand));
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(LongPressBehavior));
/// <summary>
/// Gets or sets the command parameter.
/// </summary>
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
/// <summary>
/// Gets or sets the command.
/// </summary>
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
protected override void OnAttachedTo(Button button)
{
base.OnAttachedTo(button);
this.BindingContext = button.BindingContext;
button.Pressed += Button_Pressed;
button.Released += Button_Released;
}
protected override void OnDetachingFrom(Button button)
{
base.OnDetachingFrom(button);
this.BindingContext = null;
button.Pressed -= Button_Pressed;
button.Released -= Button_Released;
}
/// <summary>
/// DeInitializes and disposes the timer.
/// </summary>
private void DeInitializeTimer()
{
lock (_syncObject)
{
if (_timer == null)
{
return;
}
_timer.Change(Timeout.Infinite, Timeout.Infinite);
_timer.Dispose();
_timer = null;
Debug.WriteLine("Timer disposed...");
}
}
/// <summary>
/// Initializes the timer.
/// </summary>
private void InitializeTimer()
{
lock (_syncObject)
{
_timer = new Timer(Timer_Elapsed, null, _duration, Timeout.Infinite);
}
}
private void Button_Pressed(object sender, EventArgs e)
{
_isReleased = false;
InitializeTimer();
}
private void Button_Released(object sender, EventArgs e)
{
_isReleased = true;
DeInitializeTimer();
}
protected virtual void OnLongPressed()
{
var handler = LongPressed;
handler?.Invoke(this, EventArgs.Empty);
if (Command != null && Command.CanExecute(CommandParameter))
{
Command.Execute(CommandParameter);
}
}
public LongPressBehavior()
{
_isReleased = true;
_duration = Duration;
}
public LongPressBehavior(int duration) : this()
{
_duration = duration;
}
private void Timer_Elapsed(object state)
{
DeInitializeTimer();
if (_isReleased)
{
return;
}
Device.BeginInvokeOnMainThread(OnLongPressed);
}
}
}
In the XAML UI:
<Button x:Name="MyButton" Text="Long Press Me!">
<Button.Behaviors>
<behaviors:LongPressBehavior LongPressed="MyButton_LongPressed"/>
</Button.Behaviors>
</Button>
XAML UI with Command Binding:
<Button x:Name="MyButton" Text="Long Press Me!">
<Button.Behaviors>
<behaviors:LongPressBehavior Command="{Binding CommandInViewModel}"/>
</Button.Behaviors>
</Button>
Make use of XLabs.Forms nuget package, which make long press and other gesture in PCL code only.
Use of XLabs.Forms package will reduce the need of custom rendering in individual platforms...
Add XAML code in .xaml file and attached event handler in .xaml.cs file..
It is working fine in Android..
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MultiImage.Page1"
xmlns:lc="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
xmlns:lb="clr-namespace:XLabs.Forms.Behaviors;assembly=XLabs.Forms">
<ContentPage.Content>
<lc:GesturesContentView ExcludeChildren="False" GestureRecognized="GesturesContentView_GestureRecognized">
<lb:Gestures.Interests>
<lb:GestureCollection>
<lb:GestureInterest GestureType="SingleTap"/>
<lb:GestureInterest GestureType="LongPress"/>
<lb:GestureInterest GestureType="DoubleTap"/>
</lb:GestureCollection>
</lb:Gestures.Interests>
<Image Source="Myimage.png" Aspect="AspectFit" HeightRequest="100"/>
</lc:GesturesContentView>
</ContentPage.Content>
C# backend code:
private void GesturesContentView_GestureRecognized(object sender, GestureResult e)
{
switch (e.GestureType)
{
case GestureType.LongPress:
//Add code here
break;
case GestureType.SingleTap:
// Add code here
break;
case GestureType.DoubleTap:
// Add code here
break;
default:
break;
}
I recently came across this problem and found a useful post on the topic https://alexdunn.org/2017/12/27/xamarin-tip-xamarin-forms-long-press-effect/
This makes use of the RoutingEffect and goes through an example of how to create both iOS and Android implementation. The simplicity of this allows you to attach it to any view in your app without recreating code.
Surfing the internet I found the solution. There are few steps which you should reproduce.
1) Inherit the control you need the gestures on (i.e. if you want to add gesture to Xamarin.Forms.Image, create you own ImageWithLongPressGesture class).
public class ImageWithLongPressGesture : Xamarin.Forms.Image
{
public EventHandler LongPressActivated;
public void HandleLongPress(object sender, EventArgs e)
{
//Handle LongPressActivated Event
}
}
2) Expose public events for the needed gestures.
3) Create a Renderer for each platform.
4) In the Renderer, handle the gestures and bubble them to your control.
[assembly: ExportRenderer(typeof(ImageWithLongPressGesture), typeof(LongPressGestureRecognizerImageRenderer))]
namespace App1.Droid.DroidRenderers
{
public class LongPressGestureRecognizerImageRenderer : ImageRenderer
{
ImageWithLongPressGesture view;
public LongPressGestureRecognizerImageRenderer()
{
this.LongClick += (sender, args) => {
Toast.MakeText(this.Context, "Long press is activated.", ToastLength.Short).Show();
};
}
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if(e.NewElement != null)
{
view = e.NewElement as ImageWithLongPressGesture;
}
}
}
}
This solution is a hybrid of answer on xamarin forms forum and Touch and Gestures presentation by Telerik.
//To Add Programatically:
StackLayout _Containter = new StackLayout();
StackLayout _StackLayout = new StackLayout();
_StackLayout.Children.Add(new Label(){Text="Execute Me"});
GesturesContentView Gv = new GesturesContentView();
_StackLayout.SetValue(XLabs.Forms.Behaviors.Gestures.InterestsProperty, new GestureCollection() {
new GestureInterest() { GestureType = GestureType.SingleTap },
new GestureInterest() { GestureType = GestureType.LongPress },
new GestureInterest() { GestureType = GestureType.DoubleTap }
});
Gv.GestureRecognized += Gv_GestureRecognized;
Gv.ExcludeChildren = false;
Gv.Content = _StackLayout;
_Containter.Children.Add(Gv);
In order to get this to work properly on iOS, you need to use XLabs.Forms.XFormsAppiOS.Init(); in your AppDelegate.cs file just before the LoadApplication(new App()); statement.
The posted code from #zafar works if you register BindingContextChanged event.
(My post is only an add, to the original post from #zafar.)
Problem was:
if using CommandParameter="{Binding .}" resulting Parameter was always null.
You need to Register BindingContextChanged event in the OnAttachedTo function.
[...]
protected override void OnAttachedTo(Button button)
{
base.OnAttachedTo(button);
this.BindingContext = button.BindingContext;
button.BindingContextChanged += handleBindingContextChanged; //this was missing
button.Pressed += Button_Pressed;
button.Released += Button_Released;
}
private void handleBindingContextChanged(object sender, EventArgs e)
{
this.BindingContext = ((Button)sender).BindingContext;
}
protected override void OnDetachingFrom(Button button)
{
base.OnDetachingFrom(button);
this.BindingContext = null;
button.Pressed -= Button_Pressed;
button.Released -= Button_Released;
button.BindingContextChanged -= handleBindingContextChanged; //also don't forget this
}
[...]
sry for the errors, this is my first post (not enough Reputation for commenting).
I'm using this well documented solution to add a back button to our app. I'm setting things up like this when the App is initialized:
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += CreateNewKeyView_BackRequested;
private void CreateNewKeyView_BackRequested(object sender, BackRequestedEventArgs e)
{
NavigationService.Instance.GoBack();
}
The back button is shown on the desktop app and works as expected, navigating our Frame back to previous pages.
However, on Windows Phone, the hardware button just exits the app. The various places that I found code like this all state that this should work for the mobile hardware button, but it simply isn't working for us.
You should set e.Handled = true in your CreateNewKeyView_BackRequested method.
Don't know how you code for your NavigationService, I just tested the following code, it works by my side:
private void CreateNewKeyView_BackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null)
{
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
}
Or, for a phone, we use also special API for Hardware Buttons.
You can judge if the current using a phone Api is or not in the OnLaunched method:
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
Windows.Phone.UI.Input.HardwareButtons.BackPressed += OnBackPressed;
}
then complete the OnBackPressed method:
public void OnBackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null)
{
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
}
To do this, you need at first add the Windows Mobile Extensions for the UWP references in your project.
Here is
private void CreateNewKeyView_BackRequested(object sender, BackRequestedEventArgs e) //event handle nya untuk backbutton
{
var frame = ((Frame)Window.Current.Content);
if (frame.CanGoBack)
{
frame.GoBack();
e.Handled = true;
}
}
My scenario is , When I navigate to a new page It takes some time to load the content. And for that duration of time, If I press back key it throws exception for some reason. So I want to stop the back key behaviour for that much duration and when content is fully loaded, user can press the back key and then navigate to previous page. I just want to be clear, Is it permitted in application certification requirement from microsoft so that my app could not get rejected. so please give answer.
You could do something like this:
bool flag = false;
// Assuming this is where you can handle executions during loading
loading()
{
flag = true;
}
// After loading is completed
loadComplete()
{
flag = false;
}
// Handle back button
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (flag)
{
e.Cancel = true;
}
}
As long as you don't lock the user to never allow him to go back, it should pass the certification.
In xaml
<phone:PhoneApplicationPage
.....
BackKeyPress="PhoneApplicationPage_BackKeyPress">
In code
private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = CouldStepBack();
}
private bool CouldStepBack()
{
// todo return true, when load comleted
// else return false
}
And if you need you also can clean stack of pages (optional)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationService.CanGoBack)
{
while (NavigationService.RemoveBackEntry() != null)
{
NavigationService.RemoveBackEntry();
}
}
base.OnNavigatedTo(e);
}
Hope its help
In a SL4 application i need to restyle my TabItems (actually add a button in the header).
So i took the TabItem's control template from here and added the functionality i wanted.
This seems to work fine, (i could dynamically add tabitems) with one exception:
i think this posted control template is behaving somehow "arbitrary": every time the mouse hoovers over a non selected TabItem header, this gets selected WHITHOUT clicking!! (afaik this is not the default behavior: the user user has to click a header to make this tabitem the selected one).
I tried to find why it is behaving like this, with no luck!
Is there someone who can enlighten my darkness???
Thanks in advance!
Well it turns out the error was not in the control template but in the class, the style was applied to.
In detail: the class the style was applied to is the following (in it you will see my comment about the "wrong behavior"):
public class WorkspaceViewModel : TabItem
{
public WorkspaceViewModel()
{
DefaultStyleKey = typeof(WorkspaceViewModel);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Button closeButtonSel = base.GetTemplateChild("PART_CloseTopSelected") as Button;
Button closeButtonUnsel = base.GetTemplateChild("PART_CloseTopUnSelected") as Button;
if (closeButtonSel != null)
closeButtonSel.Click += new RoutedEventHandler(closeButtonSel_Click);
if (closeButtonUnsel != null)
closeButtonUnsel.Click += new RoutedEventHandler(closeButtonSel_Click);
//this part is causing the effect i was complaining about!
//and has to be removed
this.MouseEnter += delegate(object sender, MouseEventArgs e)
{
IsSelected = true;
};
}
void closeButtonSel_Click(object sender, RoutedEventArgs e)
{
//this is the close request method used in the CloseTabItemCommand
OnRequestClose();
}
#region CloseTabItemCommand
private RelayCommand closeTabItemCommand;
public ICommand CloseTabItemCommand
{
get
{
if (this.closeTabItemCommand == null)
this.closeTabItemCommand = new RelayCommand(p => this.OnRequestClose(), p => this.CanCloseTabItem());
return this.closeTabItemCommand;
}
}
private bool CanCloseTabItem()
{
return true;
}
public event EventHandler RequestClose;
private void OnRequestClose()
{
if (RequestClose != null)
RequestClose(this, EventArgs.Empty);
}
#endregion
}