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

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.

Related

OnAppearing() method is performing before calling the OnCurrentPageChanged() method

For the first time I'm restricting the onAppearing() methods in all child pages of tabbed page. I need to call the onAppearing() when I change the tab. For that, I'm using OnCurrentPageChanged() to call the onAppearing() method.
When I change the tab, I'm calling the OnCurrentPageChanged() and giving them access to run the onAppearing() functionality. onAppearing() is calling before calling the OnCurrentPageChanged().
TabbedPage code:
public partial class VendorScheduleTabbedPage : Xamarin.Forms.TabbedPage
{
public int isCount;
public VendorScheduleTabbedPage ()
{
InitializeComponent ();
Xamarin.Forms.Application.Current.Properties["dayOnAppear"] = false;
Xamarin.Forms.Application.Current.Properties["weekOnAppear"] = false;
Xamarin.Forms.Application.Current.Properties["monthOnAppear"] = false;
On<Android>().SetBarItemColor(value: Color.FromHex("#6699FF"));
On<Android>().SetBarSelectedItemColor(value: Color.Orange);
}
override protected void OnCurrentPageChanged()
{
isCount = 1;
if (this.CurrentPage.Title == "Week")
{
Xamarin.Forms.Application.Current.Properties["weekOnAppear"] = true;
}
if (this.CurrentPage.Title == "Month")
{
Xamarin.Forms.Application.Current.Properties["monthOnAppear"] = true;
}
else
{
Xamarin.Forms.Application.Current.Properties["dayOnAppear"] = true;
}
base.OnCurrentPageChanged();
}
}
}
Week Page code(child page):
public WeekSchedulePage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
timeSlot = new List<VendorScheduleTimeSlot>();
scheduleSlots = new List<VendorScheduleTimeSlot>();
lstVendorsData = new List<ScheduledCustomersVM>();
SortedList = new List<ScheduledCustomersVM>();
scheduledCustomersList = new List<ScheduledCustomersVM>();
rescheduledCustomersList = new List<RescheduledCustomersVM>();
ConfirmBtn.IsVisible = true;
ConfirmBtn.IsEnabled = false;
vendorDayAndHoursDataVM = new VendorDayAndHoursDataVM();
lstDaysAndHours = new List<VendorDayAndHoursDataVM>();
lstQuestionsData = new List<VendorQuestionsDataVM>();
overlay.IsVisible = false;
Alert.IsVisible = false;
presentWeekDay.Text = DateTime.Now.ToString("dddd, dd MMMM yyyy");
currentDayName = DateTime.Now.DayOfWeek.ToString();
currentDate = DateTime.Parse(presentWeekDay.Text);
}
protected override void OnAppearing()
{
var isAppear = Convert.ToBoolean(Application.Current.Properties["weekOnAppear"].ToString());
if (isAppear == true)
{
ConfirmBtn.IsVisible = true;
ConfirmBtn.IsEnabled = false;
overlay.IsVisible = false;
Alert.IsVisible = false;
Application.Current.Properties["dayOnAppear"] = true;
Application.Current.Properties["monthOnAppear"] = true;
ConfirmBtn.IsEnabled = false;
scheduledCustomersList.Clear();
rescheduledCustomersList.Clear();
presentWeekDay.Text = DateTime.Now.ToString("dddd, dd MMMM yyyy");
currentDayName = DateTime.Now.DayOfWeek.ToString();
weekwiseTimeslotClick();
base.OnAppearing();
}
}
Here I need to call OnCurrentPageChanged() method first instead of the OnApearing() method. And OnCurrentPageChanged() will give the bool value to perform the code which is in OnApearing() method.
In Android, onAppearing is called before OnCurrentPageChanged while in iOS OnCurrentPageChanged is called before onAppearing.
1.As jgoldberger suggested, you can call method in each Page after CurrentPageChanged:
override protected void OnCurrentPageChanged()
{
if (this.CurrentPage.Title == "Week")
{
Xamarin.Forms.Application.Current.Properties["weekOnAppear"] = true;
NavigationPage naviPage = this.Children[0] as NavigationPage;
WeekPage page = naviPage.RootPage as WeekPage;
page.test();
}else if (this.CurrentPage.Title == "Month")
{
Xamarin.Forms.Application.Current.Properties["monthOnAppear"] = true;
NavigationPage naviPage = this.Children[1] as NavigationPage;
MonthPage page = naviPage.RootPage as MonthPage;
page.test();
}
else
{
Xamarin.Forms.Application.Current.Properties["dayOnAppear"] = true;
NavigationPage naviPage = this.Children[2] as NavigationPage;
DayPage page = naviPage.RootPage as DayPage;
page.test();
}
base.OnCurrentPageChanged();
}
}
2.You can use messaging-center to notify specific page to perform some actions after CurrentPageChanged:
override protected void OnCurrentPageChanged()
{
string testStr;
if (this.CurrentPage.Title == "Week")
{
testStr = "Week";
}else if (this.CurrentPage.Title == "Month")
{
testStr = "Month";
}
else
{
testStr = "Day";
}
MessagingCenter.Send<object, string>(new object(), "CurrentPageChanged", testStr);
base.OnCurrentPageChanged();
}
And in each page:
public partial class MonthPage : ContentPage
{
public MonthPage()
{
InitializeComponent();
MessagingCenter.Subscribe<object, string>(new object(), "CurrentPageChanged", async (sender, arg) =>
{
if (arg == "Month")
{
Console.WriteLine(arg);
//do something
}
});
}
public void test() {
Console.WriteLine("test");
//do something
}
}
BTW, you should use if...else if...else instead of if...if...else in your control statement.

How to implement TabLayout.IOnTabSelectedListener.OnTabUnselected with TabbedPage.ToolbarPlacement="Bottom" - Xamarin Forms?

I just recently used android:TabbedPage.ToolbarPlacement="Bottom". I used to have the following code:
void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
{
var playPage = Element.CurrentPage as NavigationPage;
if (!(playPage.RootPage is PhrasesFrame))
return;
var tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
var playTab = tabLayout.GetTabAt(4);
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
Anyone knows how can I implement this with ToolbarPlacement="Bottom" ? I have implemented both BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener but can't find any reference for UnselectedTab if there is any.
Edit:
Previous custom renderer using the default tab position and implementing TabLayout:
namespace Japanese.Droid
{
public class MyTabbedPageRenderer: TabbedPageRenderer, TabLayout.IOnTabSelectedListener
{
ViewPager viewPager;
TabLayout tabLayout;
bool setup;
public MyTabbedPageRenderer(Context context): base(context){ }
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// More codes here
}
void TabLayout.IOnTabSelectedListener.OnTabReselected(TabLayout.Tab tab)
{
UpdateTab(tab);
}
void TabLayout.IOnTabSelectedListener.OnTabSelected(TabLayout.Tab tab)
{
UpdateTab(tab);
}
void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
{
var playPage = Element.CurrentPage as NavigationPage;
if (!(playPage.RootPage is PhrasesFrame))
return;
var tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
var playTab = tabLayout.GetTabAt(4);
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
void UpdateTab(TabLayout.Tab tab)
{
// To have the logic only on he tab on position 1
if (tab == null || tab.Position != 4)
{
return;
}
if (tab.Text == "Play")
{
tab.SetText("Pause");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
App.pauseCard = false;
}
else
{
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
}
}
}
Current custom renderer using the ToolbarPlacement="Bottom":
namespace Japanese.Droid
{
public class BottomTabPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener
{
public BottomTabPageRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
// More codes here
}
bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
base.OnNavigationItemSelected(item);
UpdateTab(item)
}
void BottomNavigationView.IOnNavigationItemReselectedListener.OnNavigationItemReselected(IMenuItem item)
{
UpdateTab(item);
}
void UpdateTab(IMenuItem item)
{
var playTabId = 4;
var title = item.TitleFormatted.ToString();
if (item == null || item.ItemId != playTabId)
{
return;
}
if (item.ItemId == playTabId)
{
if (title == "Play")
{
item.SetTitle("Pause");
item.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
App.pauseCard = false;
}
else
{
item.SetTitle("Play");
item.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
}
}
}
}
So now my problem is I don't have any idea how will I implement the TabLayout.IOnTabSelectedListener.OnTabUnselected in the new custom renderer.
There is no official stuff for OnTabReselected event for TabbedPage's bottom navigation or
BottomNavigationView because It doesn't use TabLayout.Tab for a start. Many overridden methods of TabbedPageRenderer not being called like SetTabIcon. If you are using IOnTabSelectedListener interface(As your first part of code) you have three methods to use.
void OnTabReselected(Tab tab);
void OnTabSelected(Tab tab);
void OnTabUnselected(Tab tab);
But when it comes to BottomNavigationView interface you have only two methods
void OnNavigationItemReselected
bool OnNavigationItemSelected
So we don't have built in OnTabUnselected method. Here you need to write custom code to make unseleted event.
I have tried this code without using custom renderer using 4 tabs pages & the xaml of tabbed written in MailPage.xaml file. First declare List<string> in App.xaml.cs file to store Title of all tabs
public static List<string> Titles {get;set;}
Add tabs pages title in above list from MainPage.xaml.cs file's OnAppearing method
protected override void OnAppearing()
{
for (int i = 0; i < this.Children.Count; i++)
{
App.Titles.Add(this.Children[i].Title);
}
}
Now go to your MyTabbedPage class in which is available in shared project.
public class MyTabbedPage : Xamarin.Forms.TabbedPage
{
string selectedTab = string.Empty;
string unSelectedTab = string.Empty;
bool isValid;
public MyTabbedPage()
{
On<Xamarin.Forms.PlatformConfiguration.Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
this.CurrentPageChanged += delegate
{
unSelectedTab = selectedTab;
selectedTab = CurrentPage.Title;
if (App.Titles != null)
isValid = true;
else
App.Titles = new List<string>();
if (isValid)
{
MoveTitles(selectedTab);
//Pass 0 index for tab selected & 1 for tab unselected
var unSelecteTabTitle = App.Titles[1];
//TabEvents(1); here you know which tab unseleted call any method
}
};
}
//This method is for to moving selected title on top of App.Titles list & unseleted tab title automatic shifts at index 1
void MoveTitles(string selected)
{
var holdTitles = App.Titles;
if (holdTitles.Count > 0)
{
int indexSel = holdTitles.FindIndex(x => x.StartsWith(selected));
holdTitles.RemoveAt(indexSel);
holdTitles.Insert(0, selected);
}
App.Titles = holdTitles;
}
}
Or you can make swith case like this
void TabEvents(int index)
{
switch (index)
{
case 0:
//Tab selected
break;
case 1:
//Tab unselected
break;
}
}
Few things I should mention that MainPage.xaml.cs file inheriting MyTabbedPage
public partial class MainPage : MyTabbedPage
Structure of MainPage.xaml file
<?xml version="1.0" encoding="utf-8" ?>
<local:MyTabbedPage
<TabbedPage.Children>
<NavigationPage Title="Browse">
</NavigationPage>
</TabbedPage.Children>
</local:MyTabbedPage>
Answer seems long but hope it help you.
As per G.Hakim's suggestion, I was able to do what I wanted to do by capturing the tab item I wanted to work on and do the necessary actions in BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected.
namespace Japanese.Droid
{
public class BottomTabPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener
{
// same as above
bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
base.OnNavigationItemSelected(item);
if(item.ItemId == 4 && item.TitleFormatted.ToString() == "Play")
{
item.SetTitle("Pause");
item.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
App.pauseCard = false;
playTab = item;
}
if(item.ItemId !=4 && playTab.TitleFormatted.ToString() == "Pause")
{
playTab.SetTitle("Play");
playTab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
return true;
}
// same as above
}
}

Trying to retrieve result using linq

Hi I have a table which has a column AllowStockEdit which is a bit
I am trying to check is a user has edit access and then show edit and delete buttons on a radgridview
this is the code I am using
protected void AccessLevels(object sender, EventArgs e)
{
LINQDataContext dc = new LINQDataContext();
UserPermission up = dc.UserPermissions.Where(a => a.ID == (int)Session["Permission"]).SingleOrDefault();
up.AllowStockEdit = true;
}
/*show hide buttons */
protected void SelectedStockGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// show the edit button when user has correct access level
if
{
Button btnEdit = (Button)e.Row.FindControl("ShowEditButton");
Button btndelete = (Button)e.Row.FindControl("ShowDeleteButton");
btnEdit.Visible = true;
btndelete.Visible = true;
}
}
}
I am trying to check to see if the user has edit access if they do show the buttons
any help appreciated
Something like that:
protected bool AccessLevels()
{
LINQDataContext dc = new LINQDataContext();
return dc.UserPermissions.Where(a => a.ID == (int)Session["Permission"]).SingleOrDefault().AllowStockEdit;
}
protected void SelectedStockGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// show the edit button when user has correct access level
if(AccessLevels() == true)
{
Button btnEdit = (Button)e.Row.FindControl("ShowEditButton");
Button btndelete = (Button)e.Row.FindControl("ShowDeleteButton");
btnEdit.Visible = true;
btndelete.Visible = true;
}
}
}

Data grid view in win form does not re size with its content

I am trying to re size the data grid view in windows form. There are two data grid view on my form and both are fed from the database. Is there any was I can resize the data grid view on the left so that it grows with the content length and width and the data grid view shrinks with the content.
Given below is my code
private void show_Click(object sender, EventArgs e)
{
int rowIndex = Convert.ToInt32(productGridView.SelectedRows[0].Cells[2].Value);
//IEnumerable<Supplier> supplierQuery = from supplier in newNorthWindContext.Suppliers
// where supplier.SupplierID == rowIndex
// select new {} supplier;
IEnumerable<Supplier> supplierQuery = newNorthWindContext.Suppliers.Where(supliers => supliers.SupplierID == rowIndex);
supplierDataGridView.DataSource = ((ObjectQuery)supplierQuery).Execute(MergeOption.AppendOnly);
supplierDataGridView.Columns["SupplierID"].Visible = false;
supplierDataGridView.Columns["ContactTitle"].Visible = false;
supplierDataGridView.Columns["Address"].Visible = false;
supplierDataGridView.Columns["City"].Visible = false;
supplierDataGridView.Columns["Region"].Visible = false;
supplierDataGridView.Columns["PostalCode"].Visible = false;
supplierDataGridView.Columns["ContactTitle"].Visible = false;
supplierDataGridView.Columns["Address"].Visible = false;
//supplierDataGridView.AutoResizeColumns();
supplierDataGridView.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
}
private void categoryDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
Category category = (Category)this.categoryDropDown.SelectedItem;
try
{
productGridView.DataSource = category.Products;
productGridView.Columns["SupplierID"].Visible = false;
productGridView.Columns["CategoryID"].Visible = false;
productGridView.Columns["Category"].Visible = false;
productGridView.Columns["Order_Details"].Visible = false;
productGridView.Columns["Supplier"].Visible = false;
productGridView.AllowUserToDeleteRows = true;
productGridView.AutoResizeColumns();
productGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void ProductDetail_Load(object sender, EventArgs e)
{
newNorthWindContext = new NorthwindEntities();
productGridView.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
IEnumerable<Category> categoryQuery = from category in newNorthWindContext.Categories.Include("Products")
orderby category.CategoryName
select category;
try
{
this.categoryDropDown.DataSource = ((ObjectQuery)categoryQuery).Execute(MergeOption.AppendOnly);
this.categoryDropDown.DisplayMember = "categoryName";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This solves the issue.
supplierDataGridView.Width = supplierDataGridView.Columns.GetColumnsWidth(DataGridViewElementStates.Visible)+4;
at the end of show_Click you should have something like
supplierDataGridView.Width = supplierDataGridView.Columns.Sum(x => x.Width) + supplierDataGridView.RowHeadersWidth + 2;
supplierDataGridView.Height = supplierDataGridView.GetRowDisplayRectangle(supplierDataGridView.NewRowIndex, true).Bottom + supplierDataGridView.GetRowDisplayRectangle(supplierDataGridView.NewRowIndex, false).Height;
I hope this helps!

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");
}
};
}

Resources