Well, I'm developing a app in my cellphone that is going to connect to my PC, the problem is that everytime that I return a URLRequest to the cellphone, it shows the previous Form on the screen and not de actual one, for example this is what goes in my actionListener:
public void actionPerformed(ActionEvent ae) {
if (ae.getCommand() == guiaUtil.cSelecionar()) {
LoginRemote loginRemote = new LoginRemote();
try {
//This is the request, returns true or false, does not affect the form
loginRemote.login(tLogin.getText(), tPassword.getText());
} catch (Exception e) {
GuiaUtil.error(e);
return;
}
guiaUtil.mainApp().startMenu();
}
}
Then in the "guiaUtil.mainApp().startMenu()" I have this
public void startMenu() {
if (itemsMenu == null) {
itemsMenu = new List();
itemsMenu.setWidth(320);
itemsMenu.addItem("Sincronize Spots");
itemsMenu.addItem("Find Spots");
itemsMenu.addItem("Work");
itemsMenu.setFocus(true);
this.addComponent(itemsMenu);
this.addCommandListener(this);
this.addCommand(guiaUtil.cSelect());
Form form = new Form();
form.addComponent(itemsMenu);
}
form.show();
}
Anyway, after the request returns, it shows my Login form again, instead of showing the Menu List
Maybe what is going is that you are getting an exception, treating it with GuiaUtil.error and returning from actionPerformed without calling startMenu.
I would move guiaUtil.mainApp().startMenu() inside the try/catch block.
Not sure what happens in loginRemote.login(tLogin.getText(), tPassword.getText());
If you access the network, I would put that part in a different thread.
Inform the main thread by some kind of callback when the "remote login" is done,
you can show the menuForm from the edt then.
You have to put the following code outside the if condition.
Form form = new Form();
form.addComponent(itemsMenu);
You are having two form object. one inside if and another one outside of if. Object created inside the loop will loses the scope inside if. You are showing form object outside if. That's why, menu list screen was not displayed.
Related
I have created a smart panel in a custom screen to ask for user input that is used to facilitate moving stock from normal inventory into an isolation area. My original smart panel example that I always use is the Copy Order in the SOOrderEntry graph (SO301000). In this case, I need to do a bit of validation, and the user may very well decide to close the smart panel and update the document in the screen before reopening the smart panel again. If the user clicks the cancel button, I need the smart panel to reset back to defaults every time it is opened.
I thought this might be handled in the ASPX screen definition, but I can't find the right setting for the form itself. I use AutoRefresh on selectors to refresh every time they are opened, but I need the form itself to do the same and refresh back to default every time it is opened. The desired behavior DOES occur automatically when I navigate to another record of the graph's primary DAC, but I cannot seem to force the smart panel to refresh automatically every time it is opened. I looked at the various options for the form in ASPX, but I overlooked it if it is there.
Similarly to CopyOrder on SOOrderEntry, here is my code sample from my graph.
public PXFilter<StockParamFilter> stockparamfilter;
#region AddFromStock
public PXAction<MyTag> addFromStock;
[PXUIField(DisplayName = Messages.AddFromStock, MapEnableRights = PXCacheRights.Insert, MapViewRights = PXCacheRights.Insert)]
[PXButton]
protected virtual IEnumerable AddFromStock(PXAdapter adapter)
{
MyTag tag = Tags.Current;
if (tag?.TranRefNbr != null)
{
throw new PXException(Messages.TagAlreadyReceived);
}
MyTagEntry graph = PXGraph.CreateInstance<MyTagEntry>();
WebDialogResult dialogResult = stockparamfilter.AskExt(setStockStateFilter, true);
if (dialogResult == WebDialogResult.OK || (IsContractBasedAPI && dialogResult == WebDialogResult.Yes))
{
// My Business Logic Here
}
return adapter.Get();
}
#endregion
#region CheckStockParams (OK Button in Smart Panel)
public PXAction<MyTag> checkStockParams;
[PXUIField(DisplayName = "OK", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXLookupButton]
public virtual IEnumerable CheckStockParams(PXAdapter adapter)
{
return adapter.Get();
}
#endregion
#region setStockStateFilter
private void setStockStateFilter(PXGraph aGraph, string ViewName)
{
checkStockStateFilter();
}
#endregion
#region checkStockStateFilter
protected virtual void checkStockStateFilter()
{
// My Business Logic Here to set bool enableStockParams = ???
checkStockParams.SetEnabled(enableStockParams);
}
#endregion
This seems like something I did in the past, but I cannot seem to locate the code. I think it is related to stockparamfilter being a PXFilter instead of a PXSelect (or SelectFrom).
I have tried stockparamfilter.ClearDialog() with no luck. I have tried stockparamfilter.RequestRefresh() with no luck. I even tried stockparamfilter.DeleteCurrent() which seemed to work when I hit Cancel, but then my code did not execute when I hit OK. I also seemed to get the desired results when I used stockparamfilter.Cache.SetDefaultExt<StockParamFilter.locationID>(filter); on every field, until I hit OK which did nothing. It's like every time I try to manipulate the filter, I break the smart panel without any errors in the trace. In fact, here is the list of what I tried unsuccessfully:
StockParamFilter filter = stockparamfilter.Current;
stockparamfilter.View.Clear();
stockparamfilter.View.RequestRefresh();
stockparamfilter.Cache.Clear();
stockparamfilter.View.RequestRefresh();
stockparamfilter.View.RequestFiltersReset();
stockparamfilter.DeleteCurrent();
stockparamfilter.ClearDialog();
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.locationID>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.toLocationID>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.qty>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.lotSerialNbr>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.origRefNbr>(filter);
What is the ASPX code or C# Code that will let me reset the smart panel to defaults?
A big thanks to Hughes Beausejour at Acumatica for the offline assist. Posting solution for anyone else that may have this issue.
First, it is important to understand that AskExt generates 2 passes of the code. The first pass prompts the smart panel. Upon response to the smart panel, the code executes again, but in this second context skips the ask. With that in mind, the reason for my code not working became clear, as Hughes explained to me.
To execute the code when the form is initialized, that code must be executed before the ask occurs. Otherwise, the form is presented and then the initializing code is executed too late. Additionally, it must be conditioned such that it only fires when the smart panel was not given an OK response by the user. (Not realizing the code executes twice, I was unaware that I was resetting the fields on both passes. When I could get the form to reset, the subsequent processing would fail becuase I was resetting it on that pass as well.) Following that code, the AskExt can be used to present the form along with the normal processing of the user response.
My code, to show the working example, is as follows:
StockParamFilter filter = stockparamfilter.Current;
// If the user response is anything except an affirmative, default the fields
if (!(stockparamfilter.View.Answer == WebDialogResult.OK || (IsContractBasedAPI && stockparamfilter.View.Answer == WebDialogResult.Yes)))
{
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.locationID>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.toLocationID>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.qty>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.lotSerialNbr>(filter);
stockparamfilter.Cache.SetDefaultExt<StockParamFilter.origRefNbr>(filter);
}
// Present the Smart Panel Dialog (happens only on the 1st pass - AskExt causes the code to execute twice)
WebDialogResult dialogResult = stockparamfilter.AskExt(setStockStateFilter, true);
// If the response was affirmative, execute the business logic
if (dialogResult == WebDialogResult.OK || (IsContractBasedAPI && dialogResult == WebDialogResult.Yes))
{
// Do Business Logic Based On User Response In Smart Panel
}
Suppose I want to pass one object (reference) through several pages. I can navigate and pass parameters via Frame.Navigate(typeof(FirstPage), object). But how to pass the reference back on back press properly?
protected override void OnNavigatedTo(NavigationEventArgs e) {
if (e.Parameter is SomeClass) {
this.someObject = (SomeClass)e.Parameter;
}
else {
this.someObject = new SomeClass();
}
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
SystemNavigationManager.GetForCurrentView().BackRequested += OnHardwareButtonsBackPressed;
base.OnNavigatedTo(e);
}
private void OnHardwareButtonsBackPressed(object sender, BackRequestedEventArgs e) {
// This is the missing line!
Frame.Navigate(typeof(FirstPage), this.someObject);
}
But when I press back button it goes back to the FirstPage OnNavigatedTo with no parameter, and then back to the SecondPage OnHardwareButtonsBackPressed and then back to FirstPage OnNavigatedTo with filled parameter.
Could you please advice me some better approach?
In your back handler, don't navigate forwards again, just call GoBack -- and it's typically easier if you handle that at a global level rather than at a page level.
You can store your application state (the things you want to persist across page navigations) in global / static objects, or you could directly modify the object that was passed from the initial navigation (if the calling page still has a reference, it will be able to see the changes).
I would consider doing a search for "MVVM Windows Apps" and looking at some of the results to learn about a common way of building XAML apps.
I'm working with java me, I built an app using forms displayables. I'm trying to switch to other forms, based on the user's input in a textfield item. For example, I want the user to be able to type in the number "1" in the textfield and then be taken to form1 or type in "2" and be taken to form2 etc.
What's the code to do this?
Here's what I did but it's not working as expected:
form.setItemStateListener(new ItemStateListener() {
public void itemStateChanged(Item item) {
if (item == TextField) {
if ("1".equals(TextField.getString())) {
switchDisplayable(null, form1);
}
}
}
I've done as adviced. I added a command to the textfield item and listen on it to read textfield contents and then compare the contents as a string, to switch forms. See my code below, still not working. I think maybe there's something I'm missing or my logic is not right.
form.setCommandListener(new CommandListener() {
public void commandAction(Command command, Displayable displayable) {
if (command == getTextFieldItemCommand()) {
if ("1".equals(TextField.getString())) {
switchDisplayable(null, form1);
} else if ("2".equals(TextField.getString())){
switchDisplayable(null, form2);
}
}
}
It looks like you expect method itemStateChanged to be invoked when it feels convenient to you, like at every character entry in the text field.
Above expectation is wrong, specified behavior is explained in API javadocs:
It is up to the device to decide when it considers a new value to have been entered into an Item... In general, it is not expected that the listener will be called after every change is made...
Given above, using itemStateChanged the way you want makes very little sense, consider changing design of your MIDlet.
I for one would probably just add a command Go and command listener to the form or text field and read text field contents when user invokes that command to find out which displayable they want to switch to.
In my controller, I have a before() function that calls parent::before() and then does some additional processing once the parent returns. based on a specific condition, I want to "save" the original request and pass execution to a specific action. Here is my before() function.
public function before() {
parent::before();
$this->uri = Request::Instance()->uri;
$match = ORM::factory('survey_tester')
->where('eid','=',$this->template->user->samaccountname)
->find();
if (!$match->loaded()) {
self::action_tester("add",$this->template->user);
}
}
And the action that is being called..
public function action_tester($op=null,$user=null) {
$testers = ORM::factory('survey_tester')->find_all();
$tester = array();
$this->template->title = 'Some new title';
$this->template->styles = array('assets/css/survey/survey.css' => 'screen');
$this->template->scripts = array('assets/js/survey/tester.js');
$tester['title'] = $this->template->title;
$tester['user'] = $this->template->user;
switch ($op) {
case "add":
$tester = ORM::factory('survey_tester');
$tester->name = $user->displayname;
$tester->email = $user->mail;
$tester->division = $user->division;
$tester->eid = $user->samaccountname;
if ($tester->save()) {
$this->template->content = new View('pages/survey/tester_add', $admin);
} else {
$this->template->content = new View('pages/survey/tester_error', $admin);
}
break;
default:
break;
}
}
This all seems to work fine. This is designed to prompt the user for a specific piece of information that is not provided by $user (populated by LDAP) if this is the first time they are hitting the controller for any reason.
The problem is the views are not rendering. Instead control passes back to whatever action was originally requested. This controller is called survey. If i browse to http://my.site.com/survey and login with new user info, the record gets written and i get the action_index views instead of my action_tester views.
I cannot figure out what I am doing wrong here. Any ideas will be appreciated. Thank you.
EDIT: I managed to get this working (sort-of) by using $this->request->action = 'tester'; but I'm not sure how to add/set new params for the request yet.
The issue is that you are calling your method (action_tester), but then Kohana is still going to call the original action after the before method is called, which is going to change the response content overwriting the changed made in action_tester().
You can change the action being called (after before is called) inside your before() method:
$this->request->action('action_tester');
After the before method is called, it should then call the new Action (action_tester) rather than the old one, but then you need to do something about the way you are passing your parameters then.
Or you could just redirect the request upon some condition:
if($something) {
$this->request->redirect('controller/tester');
}
This doesn't seem like a nice way to do it anyway.
In short:
I want to show a view or action sheet and only continue code execution after the user has dismissed the view / sheet. So: line one shows the view, line two reads some result variable.
In detail why I would need this:
I'm porting a Windows Forms application over to the iPad. The original implementation has a communication class which uses a web service to communicate with the server. It offers a couple of methods to get data. Conveniently it checks prior to each call if the user still has a valid connection or if he has to re-enter his password for security reasons.
If the password is required, the .NET class shows a modal dialog which blocks any further code executio and if the password was entered, retries the last call it has made before showing the dialog.
Now using CocoaTouch I'm facing a problem. I replaced the code that shows the dialog with a UIActionSheet. Works great but code execution continues immediately, whereas in Windows Forms it is blocked (the next line in Windows Forms after showing the dialogs is to read the entered password from the dialog) until the dialog has been closed.
I tried a Thread.Sleep() until the user dismisses the UIActionSheet but the Thread.Sleep() also blocks the main loop and my view won't even be drawn.
The alternative I currently see is to change all methods in the already working class and give them a return value: if password required, handle it, then retry.
But this means that all over my code I will have to add these checks because at any given moment the password might be needed. That's why it is nested in communication class in Windows Forms.
Any other ideas?
René
Yes, it is possible.
To do this, what you can do is to run the mainloop manually. I have not managed to stop the mainloop directly, so I instead run the mainloop for 0.5 seconds and wait until the user responds.
The following function shows how you could implement a modal query with the above approach:
int WaitForClick ()
{
int clicked = -1;
var x = new UIAlertView ("Title", "Message", null, "Cancel", "OK", "Perhaps");
x.Show ();
bool done = false;
x.Clicked += (sender, buttonArgs) => {
Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
clicked = buttonArgs.ButtonIndex;
};
while (clicked == -1){
NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));
Console.WriteLine ("Waiting for another 0.5 seconds");
}
Console.WriteLine ("The user clicked {0}", clicked);
return clicked;
}
I think this approach using async/await is much better, and doesn't suffer from freezing the app when rotating the device, or when the autoscrolling interferes and leaves you stuck in the RunUntil loop forever without the ability to click a button (at least these problems are easy to reproduce on iOS7).
Modal UIAlertView
Task<int> ShowModalAletViewAsync (string title, string message, params string[] buttons)
{
var alertView = new UIAlertView (title, message, null, null, buttons);
alertView.Show ();
var tsc = new TaskCompletionSource<int> ();
alertView.Clicked += (sender, buttonArgs) => {
Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
tsc.TrySetResult(buttonArgs.ButtonIndex);
};
return tsc.Task;
}