How to pushasync from detailpage in masterdetailpage? - ios

From the detailpage's view I try to push a new page on and I get this error: **
System.InvalidOperationException: Page must not already have a parent.
I keep trying different things but nothing works. Is there a way to push a page onto it, I mean, the detailpage is a navigationpage but it is a detailpage. Any and all help is much appreciated.
I am using xamarin forms labs ViewFactory.
//app.cs GetMainPage
var rootPage = ViewFactory.CreatePage<HomeVM>();
//in HomeView.xaml.cs, setting the detailpage to the list of messages
Detail = new NavigationPage(ViewFactory.CreatePage<MessagesVM>());
//This is in the MessagesView to show an individual message with a back button to the list of messages
Navigation.PushAsync(ViewFactory.CreatePage<MessageDetailVM>());

If you already have a NavigationPage, do not create another one to wrap your Detail instance in.
Detail = iewFactory.CreatePage<MessagesVM>();
Navigation.PushAsync(ViewFactory.CreatePage<MessageDetailVM>());

On my part, I also having the same error using MessagingCenter, but also solve it by unsubscribing/disposing after page closing/OnDisappearing.
Hope it helps.
public partial class MainPage : MasterDetailPage
{
public MainPage()
{
InitializeComponent();
MasterBehavior = MasterBehavior.Popover;
MessagingCenter.Subscribe<NavigationPage>(this, "Navigate", (pageItem) =>
{
Detail = pageItem;
IsPresented = false;
});
MessagingCenter.Subscribe<string>(this, "Logout", (s) =>
{
Application.Current.MainPage = new LoginPage("", "");
});
}
protected override void OnDisappearing()
{
MessagingCenter.Unsubscribe<NavigationPage>(this, "Navigate");
MessagingCenter.Unsubscribe<string>(this, "Logout");
base.OnDisappearing();
}
}
Unfortunately, I encountered this error again, and I solve it by using this setting the NavigationPage Parent property to null.
MessagingCenter.Subscribe<NavigationPage>(this, "Navigate", (pageItem) =>
{
pageItem.Parent = null; //solution
Detail = pageItem;
IsPresented = false;
});

Both answers before mine are pointing to the right direction, so this is just an addition. The key is in fact to not create the NavigationPage/NavigationView again.
In my project, I am using static objects for the MasterDetailPage, the NavigationView and the corresponding ViewModels in Xamarin Forms App class;
I am only creating an instance if their Value is null, which is likely to happen only if the app was closed before (no matter if closed by the user or the OS). If the app is still running (resumed), I am just using the already existing objects to restore the state.
This solved all these problems for me, and I hope it is helpful for someone else.

Try using the Navigation property of the Detail object like this:
Detail.Navigation.PushAsync(page);
To push a new page on my Detail I use the code below:
Note there I'm using a ListView with page options in MasterDetailPage
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MainMenuItem;
if (item == null)
return;
var page = (Page)Activator.CreateInstance(item.TargetType);
//Detail = new NavigationPage(page);
Detail.Navigation.PushAsync(page);
IsPresented = false;
MasterPage.ListView.SelectedItem = null;
}

Related

Xamarin crash file # xamarin_get_block_descriptor

I am new to iOS Crash debugging but I managed to find the crash file and and symbolicate it (I think? I pressed the button in any case). Here is the thread that crashed info. It occurs occasionally on the load of one specific view:
The view initializes the view model and starts a timer:
InitializeComponent();
var vm = new OpenBatchesViewModel();
this.BindingContext = vm;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>{ some code here})
and the view model calls out to an API for some data:
public OpenBatchesViewModel()
{
SearchString = string.Empty;
CutOff = RemitStationApiService.GetCutOffTime().Result;
Username = RemitStationApiService.GetUsername();
_openBatches = RemitStationApiService.GetOpenBatches().Result.ToList();
CurrentBatchList = new ItemObservableCollection<OpenBatch>(_openBatches);
CurrentBatchList.ItemPropertyChanged += _currentBatchList_ItemPropertyChanged;
OpenContextMenuCommand = new Command<OpenBatch>(batch => BatchButtonClick(batch));
Activity = false;
}
The view model implements INotifyPropertyChanged.
TIA
Check out Microsoft AppCenter's diagnostic abilities to track crashes.

Vaadin 14 File downloading on Button Click not works

I am using https://vaadin.com/directory/component/file-download-wrapper
with below code
exportButton = new Button("export"));
FileDownloadWrapper buttonWrapper = new FileDownloadWrapper(
new StreamResource(genericGridView.getExportFileCaption(), () -> getExportStream()));
buttonWrapper.wrapComponent(exportButton);
buttonLayout.add(exportButton); //Button Layout is an Horizontal Layout which is added finally in the
main Layout.
and this part of code is written at the loading time of my view. But the method getExportStream method not getting executed(Tried to Put debug in eclipse but it never executed) neither on view load nor in button click event.
Please can you help in this implementation, whether I am doing something wrong here?
You need to add the FileDownloadWrapper to the layout instead of the Button. Otherwise, the FileDownloadWrapper does nothing.
For me the code using FileDownloadWrapper looks correct. So I tend to think that the problem is more related to how you generate the data. I copy here one code snippet from my test apps that works. The CSV export here uses StatefulBeanToCsv and StatefulBeanToCsvBuilder from com.opencsv.opencsv library.
private void export(Grid<Person> grid, TextArea result) {
Set<Person> selection = grid.asMultiSelect().getValue();
Stream<Person> persons = persons = selection.stream();
StringWriter output = new StringWriter();
StatefulBeanToCsv<Person> writer = new StatefulBeanToCsvBuilder<Person>(
output).build();
try {
writer.write(persons);
} catch (CsvDataTypeMismatchException
| CsvRequiredFieldEmptyException e) {
output.write("An error occured during writing: " + e.getMessage());
}
result.setValue(output.toString());
StreamResource resource = new StreamResource("export.csv",
() -> new ByteArrayInputStream(output.toString().getBytes()));
FileDownloadWrapper download = new FileDownloadWrapper(resource);
Button button = new Button("Click to download");
download.wrapComponent(button);
add(download);
}

EntityFramework SaveChanges() throws concurrent transaction error

In my MVC application, I have a page that loads a record from my POLICIES table and then uses it in my View. My View then has the data from this record displayed on the page, however in order to edit the record data the user needs to click the "Edit Policy" button, which launches a jQuery UI dialog with the same record in EDIT mode. I realize I could just allow them to edit it from the main View, however that is not what my client wants.
The trouble I'm having is, when I'm in my jQuery UI Dialog, I get the error below when I try to save the record.
FirebirdSql.Data.FirebirdClient.FbException: lock conflict on no wait
transaction
The Controller method for my dialog executes the following code. The PolicyModel is simply a class which serves as the ViewModel for the dialog, and the Policy property is an object representing the Policy table.
public ActionResult Policy(int policyNo) {
PolicyModel policyModel = new PolicyModel();
policyModel.Policy = dbContext.POLICIES.FirstOrDefault(db => db.POLICY_NO == policyNo);
return View(policyModel);
}
In the "Policy" View, I do a standard form using:
#using (Html.BeingForm("SavePolicy", "MyController", FormMethod.Post)) {
//hidden element for policyNo created with #Html.HiddenFor
//form elements here created using the #Html.TextBoxFor..etc.
}
The dialog button to save simply creates new FormData with var formData = new FormData($('#myformid').get(0)); I then pass that to my save controller method.
The Save method is set up like the following
public ActionResult SavePolicy(PolicyModel policyModel) {
var policy = dbContext.POLICIES.FirstOrDefault(db => db.POLICY_NO == policyModel.POLICY_NO);
if (TryUpdateModel(policy,"Policy", updateFields.ToArray())) {
dbContext.Entry(policy).State = EntityState.Modified;
dbContext.SaveChanges();
}
return Json( new { result = 1, JsonRequestBehavior.AllowGet } );
}
If I change the POLICY_NO manually though to ANY other policy number than the one currently active in the dialog like this...
var policy = dbContext.POLICIES.FirstOrDefault(db => db.POLICY_NO == 12345);
The save will update correctly.
It's like the dialog View is holding onto the resource or something. any ideas?
UPDATE
For reference, the dbContext is scoped to the Controller class in which my SavePolicy method lives as seen below...
public class MainController : Controller {
private DBModel dbContext = new DBModel();
// other methods
public ActionResult SavePolicy(PolicyModel policyModel) {
// method code as see above
}
}
ASP.NET MVC Controllers usually have this:
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
So, if you are declaring your context outside of your action, you should verify if this method is implemented.
Turns out that, at the first execution (a select), your context keeps track of the record at Firebird and it is never disposed. The second execution will try to select the same entry again, which is still tracked by another context that was not disposed properly.
Using the scoped context inside each action is another way to solve, but it is a bit more cumbersome in my standpoint.

DevExpress CallbackPanel PerformCallback hangs when content includes PageControl or TabControl

I would like to refresh the tabs in my TabControl on demand, when a separate client action occurs on the page. I have placed my TabControl extension (tried PageControl also) within a CallbackPanel, and the EndCallBack event never fires. If ShowLoadingPanel is set to true, you see that the call is hanging because the loading panel never disappears. Both OnBeginCallback and the actual Controller callback action are executed. I assume there are some sort of conflicting callbacks occuring between the panel and tabs but I cannot figure out how to resolve it. If I replace the TabControl with basic html or other simpler DevExpress controls, everything works fine.
TabControl Partial (CallbackTestPageControl.cshtml):
#Html.DevExpress().TabControl(settings => {
settings.Name = "testTabControl";
settings.Width = Unit.Percentage(100);
settings.Tabs.Add("tab 1");
settings.Tabs.Add("tab 2");
settings.Tabs.Add("tab 3");
}).GetHtml()
Panel Partial (CallbackTestPanel.cshtml):
#Html.DevExpress().CallbackPanel(settings =>
{
settings.Name = "cbpTabStrip";
settings.CallbackRouteValues = new { Controller = "Home", Action = "CallbackTestPanel" };
settings.ClientSideEvents.BeginCallback = "OnBeginCallback";
settings.ClientSideEvents.EndCallback = "OnEndCallback";
settings.SetContent(() => Html.RenderPartial("CallbackTestPageControl"));
}).GetHtml()
View (CallbackTest.cshtml):
<script type="text/javascript">
var testId = null;
function ButtonClicked(s, e) {
alert('click');
testId = 1;
if (!cbpTabStrip.InCallback())
cbpTabStrip.PerformCallback();
}
function OnBeginCallback(s, e) {
alert('begin');
e.customArgs["Id"] = testId;
testId = null;
}
function OnEndCallback(s, e) {
alert('end');
if (testId != null)
cbpTabStrip.PerformCallback();
}
</script>
#Html.DevExpress().Button(settings => {
settings.Name = "CallbackButton";
settings.Text = "Callback";
settings.ClientSideEvents.Click = "ButtonClicked";
}).GetHtml()
#Html.Partial("CallbackTestPanel")
Controller (HomeController.cs):
public ActionResult CallbackTest()
{
return View();
}
public ActionResult CallbackTestPanel()
{
int id = !String.IsNullOrEmpty(Request.Params["Id"]) ? int.Parse(Request.Params["Id"]) : 0;
return PartialView("CallbackTestPanel");
}
ADDITIONAL INFO: Also, I have tried updating the DevExpress configuration in the web.config based on other suggestions online. Specifically - updating the enableResourceMerging attribute on the compression element to false rather than true. This seemed to allow the callback to end intermittantly. I really don't want to disable resource merging anyway, so I'm actually glad this didn't provide a reliable solution. So, this is what I currently have:
<devExpress>
<themes enableThemesAssembly="true" styleSheetTheme="" theme="Office2010Silver" />
<compression enableHtmlCompression="true"
enableCallbackCompression="true"
enableResourceCompression="true"
enableResourceMerging="true" />
<settings rightToLeft="false" />
<errors callbackErrorRedirectUrl="" />
</devExpress>
I'm sorry if I wasted anyone's time on this. In the end, the problem was that I had all my non-DevExpress scripts at the bottom of my layout body. I needed to move jQuery into the head prior to the DevExpress scripts. Strangely enough, everything else had been working fine prior to this issue. Thanks to anyone who tried to reproduce.
I know this is old but my issue is I had caching enabled that form i.e.
Once I removed that everything worked. Hope this helps someone else in the future.

java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#

I've read several related posts and even posted and answer here but it seems like I was not able to solve the problem.
I have 3 Activities:
Act1 (main)
Act2
Act3
When going back and forth Act1->Act2 and Act2->Act1 I get no issues
When going Act2->Act3 I get no issues
When going Act3->Act2 I get occasional crashes with the following error: java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#.... This is a ListView cursor.
What I tried:
1. Adding stopManagingCursor(currentCursor);to the onPause() of Act2 so I stop managing the cursor when leaving Act2 to Act3
protected void onPause()
{
Log.i(getClass().getName() + ".onPause", "Hi!");
super.onPause();
saveState();
//Make sure you get rid of the cursor when leaving to another Activity
//Prevents: ...Unable to resume activity... trying to requery an already closed cursor
Cursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
stopManagingCursor(currentCursor);
}
When returning back from Act3 to Act2 I do the following:
private void populateCompetitorsListView()
{
ListAdapter currentListAdapter = getListAdapter();
Cursor currentCursor = null;
Cursor tournamentStocksCursor = null;
if(currentListAdapter != null)
{
currentCursor = ((SimpleCursorAdapter)currentListAdapter).getCursor();
if(currentCursor != null)
{
//might be redundant, not sure
stopManagingCursor(currentCursor);
// Get all of the stocks from the database and create the item list
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
((SimpleCursorAdapter)currentListAdapter).changeCursor(tournamentStocksCursor);
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
startManagingCursor(tournamentStocksCursor);
//Create an array to specify the fields we want to display in the list (only name)
String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.COLUMN_SCORE};
// and an array of the fields we want to bind those fields to (in this case just name)
int[] to = new int[]{R.id.competitor_name, R.id.competitor_score};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to);
//tournamentStocks.convertToString(tournamentStocksCursor);
setListAdapter(tournamentStocks);
}
So I make sure I invalidate the cursor and use a different one. I found out that when I go Act3->Act2 the system will sometimes use the same cursor for the List View and sometimes it will have a different one.
This is hard to debug and I was never able to catch a crashing system while debugging. I suspect this has to do with the time it takes to debug (long) and the time it takes to run the app (much shorter, no pause due to breakpoints).
In Act2 I use the following Intent and expect no result:
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(this, ActivityCompetitorDetails.class);
intent.putExtra(StournamentConstants.App.competitorId, id);
intent.putExtra(StournamentConstants.App.tournamentId, mTournamentRowId);
startActivity(intent);
}
Moving Act1->Act2 Act2->Act1 never gives me trouble. There I use startActivityForResult(intent, ACTIVITY_EDIT); and I am not sure - could this be the source of my trouble?
I would be grateful if anyone could shed some light on this subject. I am interested in learning some more about this subject.
Thanks,D.
I call this a 2 dimensional problem: two things were responsible for this crash:
1. I used startManagingCursor(mItemCursor); where I shouldn't have.
2. I forgot to initCursorAdapter() (for autocomplete) on onResume()
//#SuppressWarnings("deprecation")
private void initCursorAdapter()
{
mItemCursor = mDbHelper.getCompetitorsCursor("");
startManagingCursor(mItemCursor); //<= this is bad!
mCursorAdapter = new CompetitorAdapter(getApplicationContext(), mItemCursor);
initItemFilter();
}
Now it seems to work fine. I hope so...
Put this it may work for you:
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
orderCursor.requery();
}
This also works
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
startManagingCursor(Cursor);
}

Resources