I recently started working with data binding and I ran into a problem that I can't figure out.
I'm trying to use an interface to handle when a button is clicked but it keeps on giving me a cannot find setter attribute for onClick on the button.
In my XML file I have
android:onClick="#{() -> iCalculatorFragment.onButtonClicked()}"
In my onCreateView in my Fragment I have
mFragmentCalculatorBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_calculator, container, false);
mFragmentCalculatorBinding.setICalculatorFragment(this);
My interface method is
void onButtonClicked();
Side notes:
Inside the xml the autocomplete comes up for other methods of the interface but not the button click one. Not sure if that means anything.
Also building has drastically slowed down since using data binding. Sometimes it takes over 10 minutes to build and it ends due to an error. Any way to fix this?
Related
I have an error in my application which only happens when a user double clicks a command link.
What appears to be happening is that the first click correctly does the post then redirect and creates new instances of the WebBeans with the correct view param against them.
The second click tries to restore the old view in the POST, which will nolonger exist so creates a new one and new ViewScoped beans associated. When it comes to reading the view param in the #PostConstruct this is null and an exception is thrown later in the code.
Has anyone experienced something like this? How's best to code around it? I'm trying to avoid detecting and stopping this on the client since I'd like to understand the problem more rather than hiding it behind JS!
I found this question, but it does not appear to be resolved, and I also have more to add.
First off, the linked question defines pretty much the same issue that I am having.
1. I am using the application layout control from the ExtLib
2. It does not matter if the button is in that control or not.
3. CSJS actions will fire from the button, SSJS actions will not fire.
4. No errors are present
5. Browser / cache is irrelevant as the server side action just will not fire.
After seeing the linked question, I looked in the Local file in the package view and found an anomaly that makes me wonder if it could be the cause. I have never seen such a file before and even looked in my other xpage projects just to be sure.
This file cannot be deleted, and when clicked upon, the display window says that the element does not exist.
Does anyone know what this file is, how I can remove it, or could it be that my application is corrupted?
**More Info **
The following snippet is copied from the java file for the XPage located in the Local directory. Everything looks fine to me.
private UIComponent createEventHandler(FacesContext context,
UIComponent parent, PageExpressionEvaluator evaluator) {
XspEventHandler result = new XspEventHandler();
String sourceId = "button2/xp:eventHandler[1]/xp:this.action[1]/text()";
MethodBinding action = evaluator.createMethodBinding(result,
"#{javascript:view.postScript(\"alert(\'server script fired!\')\");}",
null,null, sourceId);
result.setAction(action);
result.setSubmit(true);
result.setEvent("onclick");
result.setRefreshMode("complete");
return result;
}
EDIT
Moving all of the design elements into a new .nsf so that file is no longer present does not change the problem of the SSJS onclick action not firing. That strange file is however not present.
Is it failing on a converter / validator? That can cause it to skip out of the lifecycle before Invoke Application phase. To test whether a button is actually working, you can also use "Do not validate or update data". Then the SSJS runs in Apply Request Values phase. If the SSJS is triggered (you won't have the latest data from the browser in the data model or components though), then it's another good bet for converter or validator failure.
I'm have a Xamarin.iOS app. It was written some time ago and used XIB to define user interface. I want to add new view (and controller for it) but every time I'm adding new page and launching the app I get the following error:
Failed to marshal the Objective-C object 0x17a37a70 (type: LoginView). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'Touch.LoginView' does not have a constructor that takes one IntPtr argument).
Additional information:
Selector: viewDidLoad
Method: Touch.LoginView:ViewDidLoad ()
What is more interesting if I'm creating new view by copying existing one and renaming it - everything works fine. I tried to figure out what is the difference but the only thing I found is the following:
If you noticed the extra level of hierarchy was added.
What it is the level and why my app continue to fail with newly created view (i have to copy existing one if I want new view).
This kind of error message can be a real pain normally. In your case, you're pretty lucky as there is a very simple fix to this. When working with xib or storyboard files, you want to have the following in your controllers:
public Test1ViewController (IntPtr handle) : base (handle)
{
}
A general explanation of the error message you are seeing:
Such issues are, 99% of the time, related to a managed instance with no
reference. At some point the GC will collect it and it will crash whenever some native code tries to callback into the (now freed) managed instance.
I have made a HomeViewModel which contains some other ViewModels to be presented in a TabParPresenter. This works fine and the ViewModels associated Views are presented correctly in their corresponding tabs. However on of the ViewModels have a check in the ctor that tells it in when some conditions apply it needs to navigate to SettingsViewModel , which is not a part of the ViewModels contained in HomeViewModel.
The navigation event gets caught by the TabBarPresenterHost, which is simply the Presenter of the application and if a TabBarPresenter is present and not null it is passed to the TabBarPresenter.ShowView() method. All this happens before the TabBarPresenter is done loading and SelectedViewController is set in ViewDidLoad. Hence the TabBarPresenter relies on using the SelectedViewController to push new Views I obviously get a Null Reference Exception.
In short what I want is:
if (conditionForShowingHome == true)
GoToHome();
else
GoToSettings();
Then when inside SettingsViewModel I have set the stuff I need when going back you return to HomeViewModel.
What breaks this is that the ViewModels are loaded before the View is done loading and the navigation event is executed before the View is done loading. Any ideas how to go around this?
I'm afraid that putting this code inside a ViewModel constructor is likely to lead to problems.
The ViewModel constructors are called during navigations - and not all platforms will support starting new navigations while existing ones are still in progress.
To workaround this, I personally opt to put this type of behaviour in the code before the navigation.
In the case of a normal navigation, this can go inside an MvxCommand execution handler.
In the case of application startup, I do this in a custom app start - see some notes in https://speakerdeck.com/cirrious/appstart-in-mvvmcross
Does MvvmCross support a cross platform solution for displaying alerts or popups?
Searching the code I found MvxDialogActivityView but it has been commented out. Will this remain the case for now?
If there is no direct support how would you suggest this is best done? (Perhaps the ViewModel would change a property and call FirePropertyChanged so that the View would be aware of it and show an alert.)
Edit 16:04 16th June 2012
What I am trying to do for this specific case is as follows:
On the page a button is clicked, which causes a method to run in the ViewModel which does an evaluation to determine which of two messages should be shown to the customer. The message would be shown as an alert or popup (either native, or preferably totally styled by me). The message would fade after (the click of the OK button, or preferably 3 seconds).
After the message has been dismissed a new page will be navigated too (depending on which of the two messages was shown).
How to handle this definitely depends on what the situation is - there's no single best rule (IMHO)
For a general error display pattern, there's one proposal at http://slodge.blogspot.co.uk/2012/05/one-pattern-for-error-handling-in.html
I've used similar patterns for showing application level notifications - e.g. for when a long running operation completes or when a chat message arrives or...
One interesting post about how to display message boxes was: http://awkwardcoder.blogspot.co.uk/2012/03/showing-message-box-from-viewmodel-in.html - I'm not sure I'd completely follow the end solution, but there are definitely some good points there about what not to do.
For your updated scenario, I would consider using a messenger (like TinyMessenger) or using normal C# events exposed by the ViewModel and consumed by its View
On the page a button is clicked, which causes a method to run in the ViewModel
I would implement this using an ICommand bound to the button Click/Tap/TouchDown
which does an evaluation to determine which of two messages should be shown to the customer.
I would definitely implement the logic within a Service
This would be called from the ViewModel - and the result/decision would probably cause some property or private field state change.
How does the View then decide to show a message? I can think of 3 options:
The View could just respond to a Property change (normal Mvvm INPC) - this would be my preference
The ViewModel could expose a normal C# event which it triggers...
The ViewModel could send a Message
This last option (Messenging) is probably the most flexible solution here - it decouples the View and ViewModel in case you later decide to change responsibilities. To implement messenging, either:
implement your own hub (like I do for errors in http://slodge.blogspot.co.uk/2012/05/one-pattern-for-error-handling-in.html)
or use a generic solution like TinyMessenger
The message would be shown as an alert or popup (either native, or preferably totally styled by me).
This is a View concern - so would be entirely controlled by the View project. I'd use controls like: UIAlert, Toast, ToastPrompt, etc - all of which can be styled
The message would fade after (the click of the OK button, or preferably 3 seconds). After the message has been dismissed...
I'd use some form of Code Behind (or maybe a Behaviour in WP7) in the View. This would detect the click/fade/disappear and would then invoke either an ICommand (my preference) or public method on the ViewModel
a new page will be navigated too
This navigation would be requested from the ViewModel
(depending on which of the two messages was shown).
This would be easy to track through the above flow... presumably the ViewModel already knows what to show.
So that's what I'd do...
it keeps the application flow logic inside the ViewModels (and lower)
it keeps the presentation inside the Views
...but I'm sure there are other options :)
One final note... the fade out and then navigate logic can really get "messed up" by Switching/Tombstoning on WP7 and Android - this may or may not matter for your particular scenario.