Refresh Page PopAsync() - c#

I have a screen that captures digital signature which, when saving or returning, executes a postasync or postmodalasync when the screen returns to me does not reload. How can I make the page reload or refresh?
<Grid BackgroundColor="WhiteSmoke" Padding="0" RowSpacing="0" VerticalOptions="StartAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentView Margin="10,0,10,5" Padding="0" BackgroundColor="LightGray" HeightRequest="500">
<StackLayout Padding="5,0,5,5" BackgroundColor="White" Spacing="1">
<Label
Text="Firma Policia Que Realizo Visita"
HorizontalOptions="Center"
TextColor="Black"
FontSize="Large"
FontAttributes="Bold"
/>
<Frame HasShadow="true"
Padding="8"
VerticalOptions="CenterAndExpand">
<signature:SignaturePadView
x:Name="SignatureView"
BindingContext="{Binding SignatureView}"
WidthRequest="280"
HeightRequest="300"
CaptionText=""
CaptionTextColor="Blue"
ClearText=""
PromptText=""
PromptTextColor="Green"
BackgroundColor="WhiteSmoke"
SignatureLineColor="Black"
StrokeWidth="3"
StrokeColor="Black" />
</Frame>
</StackLayout>
</ContentView>
</Grid>
<StackLayout Orientation="Horizontal" Padding="2" Spacing="2">
<Button
HorizontalOptions="FillAndExpand"
HeightRequest="40"
Text="Guardar"
TextColor="{x:StaticResource WhiteColor}"
FontSize="Small"
VerticalOptions="Center"
BackgroundColor="{x:StaticResource GreenButton}"
Clicked="Button_Clicked">
</Button>
<Button
HorizontalOptions="FillAndExpand"
HeightRequest="40"
Text="Limpiar"
TextColor="{x:StaticResource WhiteColor}"
FontSize="Small"
VerticalOptions="Center"
BackgroundColor="{x:StaticResource SicoqYellowColor}"
Clicked="Button_Clicked_1">
</Button>
</StackLayout>
This is the viewmodel which makes the backbuttoncommand service
public Task RemoveLastModalFromBack(object parameter,bool animated = false)
{
var mainPage = Application.Current.MainPage as NavigationView;
if (mainPage != null)
{
mainPage.Navigation.PopAsync(animated);
}
return Task.FromResult(true);
}
This is the ViewModel which receives the signature data
private async Task BackButton()
{
try
{
IsBusy = true;
await NavigationService.RemoveLastModalFromBack(str3);
o
}
catch (Exception e)
{
IsBusy = false;
// await DialogService.DisplayAlertAsync("Error", e.Message, "Aceptar");
}
finally
{
IsBusy = false;
}
}
The digital signature master page is digital signatures when you save or return the digital signatures page to reload

Do you want to achieve the result like following GIF?
If so, you can use MessagingCenter to achieve that.
We can use send method of MessagingCenter, Here is my code in the Button click event of SignaturesPage,Use the MessagingCenter to send the data to the MainPage.
private async void Button_Clicked(object sender, EventArgs e)
{
//get stream of Signatures from the pad
Stream image = await SignaturePad.GetImageStreamAsync(SignatureImageFormat.Png);
MessagingCenter.Send<Stream>(image, "Image");
await Navigation.PopAsync();
}
In the MainPage, I layout have Image to wait the stream from the SignaturesPage.
<StackLayout>
<!-- Place new controls here -->
<Frame BorderColor="Orange"
CornerRadius="10"
HasShadow="True">
<Button AutomationId="Mybutton" Text="Save" x:Name="Mybutton" HorizontalOptions="CenterAndExpand" Clicked="Mybutton_Clicked"/>
</Frame>
<Frame BorderColor="Orange"
CornerRadius="10"
HasShadow="True">
<Image x:Name="MyImage" HeightRequest="500" WidthRequest="400"/>
</Frame>
</StackLayout>
Here is my background code in the MainPage.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
MessagingCenter.Subscribe<Stream>(this, "Image", (arg) =>
{
MyImage.Source = ImageSource.FromStream(() => arg);
});
}
protected override void OnAppearing()
{
base.OnAppearing();
}
private void Mybutton_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new SignaturesPage());
}
}

Related

Popmodal from overriden back button

I am having some issues having my back button properly pop my modal after a user acknowledged that they will lose their changes if they do so. I suppose the issue lies in how to properly await the async method within a method that cannot be async due to how it is coded.
In my code behind I have the following method:
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
Task<bool> confirm = DisplayAlert("Are you sure?", "All unsaved changes will be lost", "I'm Sure", "Cancel");
confirm.ContinueWith(x =>
{
if(x.Result)
{
var task = Navigation.PopModalAsync();
task.Wait();
}
});
return true;
}
I can see that it does properly hit my breakpoint inside if the user has clicked "I'm Sure". However, after doing that the modal still remains on the page.
I call my modal using the following method (it is wrapped in a NavigationPage as I wanted to be able to leverage Toolbar items, if this is an anti pattern please let me know)
private async void EditSwipeItem_Invoked(object sender, EventArgs e)
{
var unitOfWork = container.Resolve<IUnitOfWork>();
var invoked = sender as SwipeItem;
var element = invoked.BindingContext as InventoryModel;
await Navigation.PushModalAsync(new NavigationPage(new AddEditInventoryList(true, "8dc9e483-1d63-4629-b386-680ad7c9a324", element.InventoryId, unitOfWork)));
}
The code for the backbutton is based off of what I wrote for the CancelToolBar_Clicked, and it works correctly (That is, the modal is popped after the user acknowledges the prompt).
private async void CancelToolBar_Clicked(object sender, EventArgs e)
{
bool confirm = await DisplayAlert("Are you sure?", "All unsaved changes will be lost", "I'm Sure", "Cancel");
if(confirm)
await Navigation.PopModalAsync();
}
Edit:
This is what my XAML looks like:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Invenutory.Views.Inventory.AddEditInventoryList">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Save"
Order="Primary"
Clicked="SaveToolBarItem_Clicked"
Priority="1"/>
<ToolbarItem Text="Cancel"
Order="Secondary"
Clicked="CancelToolBar_Clicked"
Priority="0"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
Padding="20">
<Frame HorizontalOptions="FillAndExpand"
VerticalOptions="Start"
Padding="20"
CornerRadius="8"
BorderColor="AliceBlue">
<StackLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="StartAndExpand">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"
Orientation="Vertical">
<Label Text="Name: " HorizontalOptions="Start" VerticalOptions="Start" />
<Entry HorizontalOptions="FillAndExpand" VerticalOptions="Start" Text="{Binding Name, Mode=TwoWay}" IsSpellCheckEnabled="True" IsTextPredictionEnabled="True" />
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"
Orientation="Vertical">
<Label Text="Description: " HorizontalOptions="StartAndExpand" VerticalOptions="Start"/>
<Editor HorizontalOptions="FillAndExpand" VerticalOptions="Start" Text="{Binding Description, Mode=TwoWay}" IsSpellCheckEnabled="True" IsTextPredictionEnabled="True" />
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"
Orientation="Vertical">
<Label Text="Count: " HorizontalOptions="Start" VerticalOptions="Start"/>
<Entry Keyboard="Numeric" HorizontalOptions="FillAndExpand" VerticalOptions="Start" Text="{Binding Count, Mode=TwoWay}" />
</StackLayout>
</StackLayout>
</Frame>
<Frame HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="20" CornerRadius="8" BorderColor="AliceBlue">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image HorizontalOptions="FillAndExpand" VerticalOptions="Start" HeightRequest="150" Aspect="AspectFit" BackgroundColor="Gray" Source="{Binding CapturedPhoto}" />
<Button Text="Take Photo" HorizontalOptions="FillAndExpand" VerticalOptions="Start" Command="{Binding TakePhotoCommand, Mode=TwoWay}"/>
</StackLayout>
</Frame>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I was able to solve this by updating my inner .ContinueWith to look as follows:
confirm.ContinueWith(x =>
{
if(x.Result)
{
MainThread.BeginInvokeOnMainThread(async () =>
{
await Navigation.PopModalAsync();
});
}
});

How to create customize popup using absolute layout?

Is there a way to use absolute layout as a customize pop-up? I am trying to create a customize popup. Is this possible?
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Yellow">
//Elements here
</StackLayout>
<AbsoluteLayout StyleClass="dialogbox" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
//Popup here
</AbsoluteLayout>
You can achieve that with AbsoluteLayout and add a fade animation. Here is running GIF.
There is code.
<StackLayout>
<Button
x:Name="btn"
Text="click"
/>
<ContentView x:Name="popupLoginView" BackgroundColor="#C0808080" Padding="10, 0" IsVisible="false" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All">
<AbsoluteLayout VerticalOptions="Center" HorizontalOptions="Center">
<StackLayout Orientation="Vertical" HeightRequest="200" WidthRequest="300" BackgroundColor="White">
<Entry Margin="20,20,20,10" Placeholder="Enter Username"></Entry>
<Entry Margin="20,0,20,0" Placeholder="Enter Password"></Entry>
<Button Margin="20,0,20,0" Text="Login"></Button>
</StackLayout>
</AbsoluteLayout>
</ContentView>
</StackLayout>
In xamarin forms, you can add fade animation to view. There is animation code.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
btn.Clicked += Btn_Clicked;
}
private async void Btn_Clicked(object sender, EventArgs e)
{
if (popupLoginView.IsVisible==true)
{
btn.IsEnabled = false;
await popupLoginView.FadeTo(0,2000);
await Task.Delay(2000);
popupLoginView.Opacity = 0;
popupLoginView.IsVisible = false;
btn.IsEnabled = true;
return;
}
if (popupLoginView.IsVisible == false)
{
if (popupLoginView.Opacity==1)
{
popupLoginView.Opacity = 0;
}
popupLoginView.IsVisible = true;
btn.IsEnabled = false;
await popupLoginView.FadeTo(1, 2000);
await Task.Delay(2000);
btn.IsEnabled = true;
popupLoginView.Opacity = 1;
return;
}
}
}
There is article about fade animation.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/animation/simple#fading
If you want to achieve it with Rg.Plugins.Popup and add the animation, you can refer to this article, it will add some animations.
https://www.c-sharpcorner.com/article/learn-about-xamarin-forms-animation-with-popuppage/

Xamarin Forms: Stacklayout Visible with System.Timers

I am on the most current version of Xamarin Forms. I have a Content Page. The Content Page has a grid that has a StackLayout and ScrollView. StackLayout Visible is false at the start point. When I click my Login Button, which has a Login method (see below) I set the StackLayout visible true. I use System.Timers too which start when login button clicked. If this timer reach 10 sec and the login isn't succesful the timer elapsed method activate. This method you can see below. At this point this work great, but I want to Login again and the StackLayout content doesn't show up. Can Anybody help me?
LoginPage.xml code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Spirocco.LoginPage"
xmlns:renderer="clr-namespace:Spirocco.Droid.Renderers">
<Grid>
<StackLayout x:Name="stackView" IsVisible="False" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="300" HeightRequest="50" BackgroundColor="LightGray" Orientation="Horizontal">
<ActivityIndicator IsRunning="True" Color="Black" HorizontalOptions="Center" Margin="20" HeightRequest="30" WidthRequest="30"/>
<Label Text="Bejelentkezés..." TextColor="Black" VerticalOptions="Center" FontSize="16"/>
</StackLayout>
<ScrollView Orientation="Both" x:Name="scrollView">
<ScrollView.Content>
<StackLayout BackgroundColor="#302138">
<Image Source="login_logo" Margin="0,0,0,0"></Image>
<StackLayout BackgroundColor="White" Margin="20,0,20,30">
<Label Text="ÜDVÖZÖLJÜK!" FontSize="30" FontFamily="Comic Sans MS" Margin="0,15,0,0" TextColor="#302138" HorizontalTextAlignment="Center"></Label>
<renderer:BaseEntry x:Name="entryEmail" Text="{Binding Email}" Placeholder="E-mail" Margin="40,0,40,0" Keyboard="Email" ReturnType="Next"/>
<renderer:BaseEntry x:Name="entryPassword" Text="{Binding Password}" Placeholder="Jelszó" IsPassword="True" Margin="40,0,40,0" ReturnType="Send"/>
<Button Text="BEJELENTKEZÉS" Clicked="Login" TextColor="White" BackgroundColor="#302138" Margin="40,10,40,0"/>
<Button Text="REGISZTRÁCIÓ" Clicked="Register" TextColor="White" BackgroundColor="#302138" Margin="40,0,40,25"/>
</StackLayout>
<Label BackgroundColor="#302138" HeightRequest="160"/>
</StackLayout>
</ScrollView.Content>
</ScrollView>
</Grid>
My login method:
private async void Login(object sender, EventArgs e)
{
if (entryEmail.Text != null && entryPassword.Text != null)
{
try
{
stackView.IsVisible = true;
scrollView.Opacity = 0.5;
timer = new Timer(10000);
timer.Start();
timer.Elapsed += SetContentViewVisible;
}
catch (Exception)
{
stackView.IsVisible = false;
scrollView.Opacity = 1;
await DisplayAlert("Hiba történt", "Sikertelen bejelentkezés", "Vissza");
}
}
else
{
await DisplayAlert("Bejelentkezés", "Sikertelen bejelentkezés, kérem a sikeres bejelentkezéshez töltse ki az e-mail cím és jelszó mezőt!", "Vissza");
}
}
SetContentViewVisible method:
private void SetContentViewVisible(object sender, ElapsedEventArgs e)
{
timer.Dispose();
scrollView.Opacity = 1;
stackView.IsVisible = false;
timer.Stop();
}
I want to refresh UI from different thread. This was problem.
private void SetContentViewVisible(object sender, ElapsedEventArgs e)
{
Device.BeginInvokeOnMainThread(
() =>
{
timer.Dispose();
scrollView.Opacity = 1;
stackView.IsVisible = false;
timer.Stop();
DisplayAlert(SaySomething);
});
}

How to add control in stacklayout of contentview in contentpage?

I am using xamarin.forms. having two projects Android and IOS.
I have one ContentView page with following code
<ContentView.Content>
<StackLayout x:Name="slMain" Padding="1" BackgroundColor="#7ABA45">
<StackLayout VerticalOptions="FillAndExpand" Padding="0,0,20,0" HeightRequest="50" HorizontalOptions="FillAndExpand">
<Label x:Name="lblTitle" VerticalOptions="CenterAndExpand" />
</StackLayout>
<StackLayout x:Name="sl" IsVisible="False" BackgroundColor="White">
</StackLayout>
</StackLayout>
</ContentView.Content>
// In Behind code(.cs file)
public ExpandCollapseStackLayout()
{
InitializeComponent();
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) =>
{
sl.IsVisible = !sl.IsVisible;
};
lblTitle.GestureRecognizers.Add(tapGestureRecognizer);
slMain.GestureRecognizers.Add(tapGestureRecognizer);
}
public string Title
{
get
{
return lblTitle.Text;
}
set
{
lblTitle.Text = value;
}
}
I want to add controls in StackLayout named "sl" of contentview in ContentPage at design time.
I dont want to add at runtime
Please suggest me how can I add Control in Contentview stacklayout?
If you want to add controls in design time simply declare them in your XAML, example:
<StackLayout x:Name="sl" IsVisible="False" BackgroundColor="White">
<!-- Add here your controls -->
<Label ... />
<Button .. />
</StackLayout>
If you want to add controls at runtime, you need to do it using your code behind page in C#. Example:
void AddControl()
{
var btn = new Button();
sl.Children.Add(btn);
}
Code for ContentView:
<ContentView.Content>
<StackLayout x:Name="slMain" Padding="1" BackgroundColor="#7ABA45" >
<StackLayout VerticalOptions="FillAndExpand" Padding="0,0,10,0" HeightRequest="50" HorizontalOptions="FillAndExpand" Orientation="Horizontal">
<Label x:Name="lblTitle" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand" Margin="10,0,0,0" TextColor="White" FontAttributes="Bold" />
<Label Text="{ x:Static local:GrialShapesFont.ArrowDown }" HorizontalOptions="End" VerticalOptions="CenterAndExpand" TextColor="White" Style="{ StaticResource FontIconBase }" FontSize="26" />
</StackLayout>
<Frame Padding="10" IsVisible="False" BackgroundColor="White" x:Name="ContentFrame" OutlineColor="Black" HasShadow="False">
</Frame>
</StackLayout>
</ContentView.Content>
CS Code for ContentView:
[ContentProperty("ContainerContent")]
public partial class ExpandCollapseStackLayout : ContentView
{
public ExpandCollapseStackLayout()
{
InitializeComponent();
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) =>
{
ContentFrame.IsVisible = !ContentFrame.IsVisible;
};
lblTitle.GestureRecognizers.Add(tapGestureRecognizer);
slMain.GestureRecognizers.Add(tapGestureRecognizer);
}
public View ContainerContent
{
get { return ContentFrame.Content; }
set { ContentFrame.Content = value; }
}
public string Title
{
get
{
return lblTitle.Text;
}
set
{
lblTitle.Text = value;
}
}
}
Add Control in ContentPage:
<control:ExpandCollapseStackLayout Title="Demo" Padding="0,10,0,0">
<control:ExpandCollapseStackLayout.ContainerContent >
<StackLayout>
<Label Text="Add Content Here"></Label>
</StackLayout>
</control:ExpandCollapseStackLayout.ContainerContent>
</control:ExpandCollapseStackLayout>

How to get the value from Listview Xamarin.form

I want to get the value from my clubid that I web service and pass it down to the next page so I would have a dynamic club detail. However, when I tried to do it, it shows me some errors. This are my codes.
ListClubs.xaml.cs
ClubApiClient service = new ClubApiClient();
public ListClubs ()
{
InitializeComponent();
}
protected async override void OnAppearing()
{
base.OnAppearing();
await setClubs(Clublistview);
}
private async Task setClubs(ListView listview)
{
var clublist = await service.getClubList(2);
listview.ItemsSource = clublist.ToList();
}
async void OnListClubsClicked(object sender, EventArgs e)
{
int clubid = int.Parse(lbId.Text); //Error msg: The name 'lbId' does not exist in the context
await Navigation.PushAsync(new DetailedClub());
}
ListClubs.xaml
<ListView x:Name="Clublistview">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="White"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="{Binding Logo}" IsVisible="true" WidthRequest="42" HeightRequest="42"/>
<Button Text="{Binding Name}" x:Name="BtnClub" AbsoluteLayout.LayoutBounds="100, 25, 100, 25" Clicked="OnListClubsClicked" TextColor="Black" VerticalOptions="FillAndExpand"/>
<Label Text="{Binding Id}" x:Name="lbId" IsVisible="false"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
using the name "lbId" isn't useful because every item in your list has a Label named "lbId".
You can use CommandParameter to add the Id to your Button
<Button Text="{Binding Name}" x:Name="BtnClub" AbsoluteLayout.LayoutBounds="100, 25, 100, 25" Clicked="OnListClubsClicked" TextColor="Black" VerticalOptions="FillAndExpand" CommandParameter="{Binding Id}" />
async void OnListClubsClicked(object sender, EventArgs e)
{
Button btn = (Button) sender;
int clubid = (int) btn.CommandParameter;
// pass the clubid to your Detail page
await Navigation.PushAsync(new DetailedClub(clubid));
}

Categories