IMessageService.ShowAsync in INavigationService.ApplicationClosing event - events

How to?
I tried these two methods, but none works. The first hangs, the second quits the program (without any exception).
private void ApplicationClosing1(object sender, ApplicationClosingEventArgs e)
{
MessageResult result = MessageResult.None;
if (!isClosing && IsDirty)
{
result = MessageService.ShowAsync("blah", "blah",
MessageButton.YesNoCancel, MessageImage.Warning)
.GetAwaiter().GetResult();
switch (result)
{
case MessageResult.Cancel:
e.Cancel = true;
return;
case MessageResult.Yes:
isClosing = true;
SaveAsync();
break;
default:
isClosing = true;
break;
}
}
}
and
private async void ApplicationClosing2(object sender, ApplicationClosingEventArgs e)
{
if (!isClosing && IsDirty)
{
var result = await MessageService.ShowAsync("blah","blah",
MessageButton.YesNoCancel, MessageImage.Warning);
switch (result)
{
case MessageResult.Cancel:
e.Cancel = true;
return;
case MessageResult.Yes:
isClosing = true;
await SaveAsync();
break;
default:
isClosing = true;
break;
}
}
}

You could solve it the same way as the DataWindows takes care of this. First set e.Cancel = true, then if the user answers, set an internal bool _reallyClose and don't set e.Cancel when this is true.

Related

Background Downloader,Download operation won't start in UWP Windows10?

I want to download files using Background Downloader.
What i have tried is?
FolderPicker folderPicker = new FolderPicker();
folderPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
folderPicker.ViewMode = PickerViewMode.Thumbnail;
folderPicker.FileTypeFilter.Add("*");
StorageFolder storgaeFolder = await folderPicker.PickSingleFolderAsync();
if (storgaeFolder != null)
{
StorageFile file = await storgaeFolder.CreateFileAsync("newnow.jpeg", CreationCollisionOption.GenerateUniqueName);
BackgroundDownloader backgroundDownloader = new BackgroundDownloader();
DownloadOperation downloadOperation = backgroundDownloader.CreateDownload(new Uri("https://www.google.com/url?sa=i&url=https%3A%2F%2Fwallpapercave.com%2Ffull-hd-wallpaper-downlord&psig=AOvVaw2_UZ_HNVNVr6fJelpyg2-S&ust=1622265707226000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCOCRzOzQ6_ACFQAAAAAdAAAAABAQ"), file);
downloadOperation.Priority = BackgroundTransferPriority.High;
Progress<DownloadOperation> progress = new Progress<DownloadOperation>(progressChanged);
CancellationTokenSource cancellationToken = new CancellationTokenSource();
try
{
await downloadOperation.StartAsync().AsTask(cancellationToken.Token, progress);
string xx = null;
}
catch (TaskCanceledException)
{
await downloadOperation.ResultFile.DeleteAsync();
downloadOperation = null;
}
}
private void progressChanged(DownloadOperation downloadOperation)
{
int progress = (int)(100 * ((double)downloadOperation.Progress.BytesReceived /(double)downloadOperation.Progress.TotalBytesToReceive));
switch (downloadOperation.Progress.Status)
{
case BackgroundTransferStatus.Running:
{
break;
}
case BackgroundTransferStatus.PausedByApplication:
{
break;
}
case BackgroundTransferStatus.PausedCostedNetwork:
{
break;
}
case BackgroundTransferStatus.PausedNoNetwork:
{
break;
}
case BackgroundTransferStatus.Error:
{
break;
}
case BackgroundTransferStatus.Completed:
{
break;
}
case BackgroundTransferStatus.Canceled:
{
break;
}
default:
{
break;
}
}
if (progress >= 100)
{
downloadOperation = null;
}
}
the execution stopped/paused at the line ---> await downloadOperation.StartAsync().The program won't run after this line and the download operation doesn't through any BackgrowndTransferStatus or Exceptions.I don't know why the code won't run after the line.

When I select No the Display Alert message displays twice why? How do I get to display alert only once when i select NO?

public async void clearswitchHandle_Toggled(object sender,
Xamarin.Forms.ToggledEventArgs e)
{
var yesSelected = await DisplayAlert("WARNING!!!", "Are you sure you want to CLEAR DATA entered", "YES", "NO");
if (yesSelected == true)
{
clearButton.IsEnabled = true;
}
else
{
clearSwitch.IsToggled = false;
}
}
Try to lock this async method, it could be called more than once:
private bool lockAlert;
public async void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
{
if (lockAlert) return;
lockAlert=true;
var ok = await DisplayAlert("WARNING!!!", "Are you sure you want to CLEAR DATA entered", "YES", "NO");
if (ok)
{
clearButton.IsEnabled = true;
}
else
{
clearSwitch.IsToggled = false;
}
lockAlert=false;
}

Xamarin, What is the difference between tab page click vs button page click?

When i click on the tab page () a new settings page comes on but it's not populated with the info i already entered but it i click on a button (Navigation.PushModalAsync(new SettingsPage());) the page comes on and its populated with info I entered. is there a difference between the two?
//for tab page
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Bldg"
x:Class="Bldg.HomePage" >
<local:HistoryLogPage Title="Log"/>
<local:AddDrainsPage Title="Add"/>
<local:SettingsPage Title="Edit Settings"/>
<Label x:Name="drain1Label" />
</TabbedPage>
//for click button
void NextpageButton_Clicked(object sender, System.EventArgs e)
{
Navigation.PushModalAsync(new SettingsPage());
}
//SettingsPage
namespace Bldg
{
public partial class SettingsPage : ContentPage
{
public static string item, username;
public static string location1, location2;
bool is1Empty = string.IsNullOrEmpty(Settings.n1LocationSettings);
bool is2Empty = string.IsNullOrEmpty(Settings.n2LocationSettings);
List<string> list;
public SettingsPage()
{
InitializeComponent();
drainquantity();
list = new List<string>();
list.Add("1");
list.Add("2");
locationPicker1.SelectedIndexChanged += drain1Handle_SelectedIndexChanged;
locationPicker2.SelectedIndexChanged += drain2Handle_SelectedIndexChanged;
//nameofpickerinxamlfile.On<iOS().SetUpdateMode(UpdateMode.WhenFinished);
locationPicker1.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
locationPicker2.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
drainxPicker.SelectedItem = Settings.DrainquantitySettings;
locationPicker1.SelectedItem = Settings.n1LocationSettings;
locationPicker2.SelectedItem = Settings.n2LocationSettings;
nameEntry.Text = Settings.NameSettings;
clearButton.IsVisible = false;
drainlocationPicker2.IsEnabled = false;
drainxPicker.SelectedItem = Settings.DrainquantitySettings;
}
//this is fired when user changes or selects new selection
void drainxHandle_SelectedIndexChanged(object sender, System.EventArgs e)
{
//to get the value of user selected going to be use in switch; then save in a
variable
var drainx = drainxPicker.Items[drainxPicker.SelectedIndex];
item = (string)drainxPicker.SelectedItem;
bool isdrainxEmpty = string.IsNullOrEmpty(Settings.DrainquantitySettings);
if (isdrainxEmpty == true)
{
//switch for user selected in drainpicker
switch (drainx)
{
case "1":
n1Gridrow.IsVisible = true;
locationPicker1.IsVisible = true;
n2Gridrow.IsVisible = false;
if (is1Empty == true)
{
drainxPicker.IsEnabled = true;
}
else
drainxPicker.IsEnabled = false;
break;
case "2":
n1Gridrow.IsVisible = true;
n2Gridrow.IsVisible = true;
locationPicker2.IsEnabled = false;
break;
} //switch end
}
else
{
drainxPicker.IsEnabled = false;
nameEntry.IsEnabled = false;
n1Gridrow.IsVisible = true;
n2Gridrow.IsVisible = true;
locationPicker1.IsEnabled = false;
locationPicker2.IsEnabled = false;
settingsaveButton.IsVisible = false;
}
}
void n1Handle_SelectedIndexChanged(object sender, System.EventArgs e)
{
location1 = (string)locationPicker1.SelectedItem;
if (is1Empty == true)
{
locationPicker2.IsEnabled = true;
n2Label.IsVisible = true;
locationPicker2.Items.Remove((string)locationPicker1.SelectedItem);
}
drainxPicker.IsEnabled = false;
locationPicker1.IsEnabled = false;
}
void n2Handle_SelectedIndexChanged(object sender, System.EventArgs e)
{
location2 = (string)locationPicker2.SelectedItem;
if (is2Empty == true)
{
locationPicker2.IsEnabled = true;
}
drainxPicker.IsEnabled = false;
locationPicker2.IsEnabled = false;
}
void nxy1()
{
foreach (var location in list)
{
locationPicker1.Items.Add(location);
}
}
void nxy2()
{
foreach (var location in list)
{
locationPicker2.Items.Add(location);
}
}
void settingsaveButton_Clicked(object sender, System.EventArgs e)
{
bool isNameEmpty = string.IsNullOrEmpty(nameEntry.Text);
if (isNameEmpty == true)
{
DisplayAlert("Enter Name", "PLEASE", "OK");
}
else
{
Navigation.PushModalAsync(new HomePage());
//saving to Settings
Settings.n1LocationSettings = location1;
Settings.n2LocationSettings = location2;
Settings.NameSettings = username;
Settings.DrainquantitySettings = item;
drainxPicker.IsEnabled = false;
}
}
void entryNameHandle_Unfocused(object sender, Xamarin.Forms.FocusEventArgs e)
{
username = nameEntry.Text;
}
void clearHandle_Clicked(object sender, System.EventArgs e)
{
Settings.ClearAllData();
}
}
}
I expect that when i click on tabbed settings page, i go to the settings page with info entered populated. just like the button click it goes to settings page already populated with user entered.
Generally, tabbed settings page and pushed settings page is the same. They are all new fresh settings page.
From your code, we can see that you are setting the value of Picker by Settings plugin:
drainxPicker.SelectedItem = Settings.DrainquantitySettings;
locationPicker1.SelectedItem = Settings.n1LocationSettings;
locationPicker2.SelectedItem = Settings.n2LocationSettings;
So, whether the info entered will be populated or not when you go to the setting page is depending on the values in Settings.
For example:
If Settings.DrainquantitySettings; has value, then drainxPicker's info will be populated.
Check the Values in your Setting when you go to tabbed settings page and pushed settings page to find any difference.

How to call MessageBox within photochooser task

I have a code where I am calling photochooser in WP7 and I want to show a messagebox to user when the pic is more than 2Mb. When I try to do this, since the photochooser task is running in background, we start getting unhandled exceptions.
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.ChosenPhoto != null)
{
ProgressBar.Visibility = Visibility.Visible;
image = _UploadImgeViewModel.ReadToEnd(e.ChosenPhoto);
if (image.Length < 16384)
{
BitmapImage bi = new BitmapImage();
bi.SetSource(e.ChosenPhoto);
UserSession.ProfileImage = bi;
Session.PreviousImage = bi;
UserSession.isImageChanged = true;
UserSession.image = image;
UserSession.Uploadimage = image;
NavigationService.Navigated += new NavigatedEventHandler(navigateCompleted);
}
else
{
ProgressBar.Visibility = Visibility.Collapsed;
UserSession.isImageChanged = false;
UserSession.ProfileImage = null;
Dispatcher.BeginInvoke(() => MessageBox.Show("The message"));
}
}
}
#endregion
This only shows the background job as resuming... and the msg box in foreground. and after a few seconds, the app crashes.
Can you please help me with this?
Cool. I got some idea to resolve this. Might not be a fix, but this way we can avoid this issue. Just add a button and do the validating process in the button click event. Since we can't display the message box when the navigation is in progress.
Below is the code:
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.ChosenPhoto != null)
{
ProcessSelectedImage(e.ChosenPhoto);
}
}
private void ProcessSelectedImage(Stream stream)
{
if (stream != null)
{
bi.SetSource(stream);
UserSession.ProfileImage = bi;
UserSession.PreviousImage = bi;
image = ConvertToImage.ReadToEnd(stream);
UserSession.image = image;
UserSession.Uploadimage = image;
}
}
private void UploadImage_Click(object sender, RoutedEventArgs e)
{
if (image.Length < 16384)
{
UserSession.isImageChanged = true;
UserSession.image = image;
UserSession.Uploadimage = image;
NavigationService.Navigate(new Uri("/Views/EditMyProfile.xaml", UriKind.Relative));
}
else
{
UserSession.isImageChanged = false;
UserSession.ProfileImage = null;
UserSession.IsChangingProfilePicture = true;
MessageBox.Show(MessageContent.ImageUploadLengh);
}
}
Thanks
Kamal
You have 10 seconds to return to the foreground completely or your app will be killed. If you have a messagebox that can display here, you will fail certification (because user could not click anything for 10 seconds) -- you need to wait for the page to load.
A workaround for this if you need to show a MessageBox is to set a bool, and check it in the Page's Loaded event.
void photoChooserTask_Completed(object sender, PhotoResult e) { if (e.ChosenPhoto != null) { ProgressBar.Visibility = Visibility.Visible;
image = _UploadImgeViewModel.ReadToEnd(e.ChosenPhoto);
if (image.Length < 16384)
{
BitmapImage bi = new BitmapImage();
bi.SetSource(e.ChosenPhoto);
UserSession.ProfileImage = bi;
Session.PreviousImage = bi;
UserSession.isImageChanged = true;
UserSession.image = image;
UserSession.Uploadimage = image;
NavigationService.Navigated += new NavigatedEventHandler(navigateCompleted);
}
else
{
ProgressBar.Visibility = Visibility.Collapsed;
UserSession.isImageChanged = false;
UserSession.ProfileImage = null;
//set flag
UserSession.ImageTooBig = true;
}
}
}
#endregion
MyPage()
{
//make sure you attach Loaded Event if not already
Loaded += (s,e) =>
{
if (UserSession.ImageTooBig)
{
UserSession.ImageTooBig = false;
MessageBox.Show("Sorry, the image exceeds 2 MB");
}
};
}

How to conditionally load edit template in telerik rad grid?

Is there a way to conditionally load different user control as edit form based on some user action (Edit vs. Create)?
This is how I ended up doing it
protected void Page_Init(object sender, EventArgs e)
{
ctlBenefitLimitsGrid.MasterTableView.EditFormSettings.EditFormType = GridEditFormType.WebUserControl;
ctlBenefitLimitsGrid.ItemDataBound += BenefitLimitsGrid_ItemDataBound;
ctlBenefitLimitsGrid.ItemCommand += BenefitLimitsGrid_ItemCommand;
ctlBenefitLimitsGrid.MasterTableView.EditFormSettings.EditFormType = GridEditFormType.WebUserControl;
}
void BenefitLimitsGrid_ItemCommand(object source, GridCommandEventArgs e)
{
switch (e.CommandName)
{
case "Edit":
e.Item.OwnerTableView.IsItemInserted = false;
ctlBenefitLimitsGrid.MasterTableView.EditFormSettings.UserControlName =
#"UserControls/BenefitLimitEdit.ascx";
break;
case "Add":
{
InsertAddControl(e);
break;
}
case "Delete":
var benefitLimitId = Convert.ToInt32(e.CommandArgument);
Presenter.Delete(benefitLimitId);
Presenter.LoadView();
break;
case "Save":
IEditView item;
if (e.Item.GetType() == typeof(GridEditFormInsertItem))
{
item =
(IEditView)e.Item.FindControl(GridEditFormItem.EditFormUserControlID);
}
else
{
item = ((GridDataItem)e.Item).EditFormItem.FindControl(GridEditFormItem.EditFormUserControlID) as IEditView;
}
if (item != null && item.HasErrors)
{
e.Canceled = true;
return;
}
e.Item.Edit = false;
ctlBenefitLimitsGrid.MasterTableView.ClearEditItems();
Presenter.LoadView();
break;
case "SaveAndNew":
{
var benefitLimitCreate = (IBenefitLimitCreate)e.Item.FindControl(GridEditFormItem.EditFormUserControlID);
if (benefitLimitCreate.HasErrors)
{
e.Canceled = true;
return;
}
Presenter.LoadView();
InsertAddControl(e);
break;
}
}
}
private void InsertAddControl(GridCommandEventArgs e)
{
ctlBenefitLimitsGrid.MasterTableView.ClearEditItems();
ctlBenefitLimitsGrid.MasterTableView.EditFormSettings.UserControlName = #"UserControls/BenefitLimitCreate.ascx";
e.Item.OwnerTableView.InsertItem();
var insertedItem = e.Item.OwnerTableView.GetInsertItem();
var ctlBenefitLimitCreate = (BenefitLimitCreate)insertedItem.FindControl(GridEditFormItem.EditFormUserControlID);
ctlBenefitLimitCreate.Presenter.LoadView();
}
I think that there was an article in the Telerik online documentation (under Insert/Update/Delete -> HowTo chapter) which does exactly what you are after.
Dick

Resources