I am using a plain vanilla UIImagePickerController with my own UIImagePickerControllerDelegate. Doing so the flash mode set by the user gets always lost as I am disposing the whole controller after each capture, so opening the camera again always sets the flash mode "back" to auto (the default value).
I could refactor my camera utility and let it live as long as the app is alive, but the better way seems to be to just get notified when the users changes the flash mode, store that mode and set it before the camera is shown again.
Setting the mode is not the problem, but I don't get notified when it is changed by the user, nor does the property of the UIImagePickerController argument within the FinishedPickingMedia method of the UIImagePickerControllerDelegate contain the latest value set by the user, it's also always "auto".
private class CameraDelegate : UIImagePickerControllerDelegate
{
public override void FinishedPickingMedia(UIImagePickerController picker, NSDictionary info)
{
// Is always UIImagePickerControllerCameraFlashMode.Auto
var foo = picker.CameraFlashMode;
}
}
Any idea how to get that information?
I think you could try using Key-Value Observing to get notified when your property is changed.
You can find a tutorial on how to get KVO working with monotouch here.
And there's always the official Apple Documentation on KVO
Related
I am writing an app in which the end user can mark documents as his favourites. I already have the necessary forms and views to save and read back the favorites, but I have one little problem: all is done in the back end (the favorites are displayed from a view, not a scoped variable) and there seems to be a sync issue between the click on the "add to favorites" link and the partial refresh that reloads the favorites: the newly added document only shows after a second refresh. No problem then, I then decided to move the favorites in a managed bean I already have for the session where I keep the language and other user's prefs.
The problem I now face is this: how can I trap the login event so I can build the favorites list in the bean? I looked at how the "xInvolve" control's favorite piece was built and I found that there is some code added to the custom control's beforePageLoad event. But I'm wandering if there's a better way of doing this. If I go that way, this means that each time a page loads, it will go in my session bean to look if it needs to build the favorites list. I feel it's a bit of an overload: I'd rather build the list once, when the user logs in.
Is that possible or I should keep the beforePageLoad code just as it is now? Any ideas/thoughts are appreciated.
Note this does NOT actually trap the login.. I'm not sure how to do that exactly but I'm not sure it's nexessary..
Just thinking out loud here.. but I would try this..
Assume you have a "UserObject" to hold the favorites for the user.. then the object gets loaded it reads them in etc...
What about an "App Bean".. a managed bean in app scope... basically a factory for your application... inside the AppBean you have a Map... so that's an easy way to get a hold of the userobject anytime and it lives throughout the app scope...
Now on each page.. you try to grab the UserObject... if it doesn't exist.. you load it once into the App Bean so it's there for later... if it exists.. it's already loaded... you then update the UserObject when the user adds/removes a favorite... make sure to go through the object in the app bean to keep it updated...
An advantage of this is if the user opens another browser or tab.. it all pulls from the AppBean...
Give that some thought and let me know if you need any help...
Also note: This is a java solution... it might be workable in SSJS though..
A standard login page is HTTP only, not XPages. HTTP identifies that a login is required, validates credentials, checks the URL that you're redirecting to exists and only then does the XPages runtime take over.
If you want to trap login, you need to have an XPage making an AJAX request to do the login.
You might want to have a look at XPages Help Application on OpenNTF. I built a favouriting function into that. Favourites are stored in the person's profile, but for the duration of the session held in memory in a Map. The person's profile is created with the hashed value of the username. There is a potential issue with renames, but that's not a significant issue.
You could use a SessionListener. In the sessionCreated method you can calculate the List and initialize your session scoped bean:
public class MySessionListener implements SessionListener {
public void sessionCreated(ApplicationEx arg0, HttpSessionEvent event) {
FavBean bean = new FavBean();
// create the favorites List
// and push it to your bean
// add the bean to session scope
event.getSession().setAttribute("favBean", bean);
}
public void sessionDestroyed(ApplicationEx arg0, HttpSessionEvent event) {}
}
We're using MVVMCross within our application and I've come up against something that I'm not sure I've solved in the best way possible.
One of our ViewModels contains 3 other view models - a dashboard and 2 lists. In iOS this is presented using a MvxTabBarViewController which works great. Android and WP present this view in a similar manner. An example of the object model is below:
public class ProjectViewModel : MvxViewModel
{
public DashboardViewModel Dashboard {get;set;}
public FirstListViewModel FirstList {get;set;}
public SecondListViewModel SecondList {get;set;}
}
We're now in the situation where if a certain action happens within the DashboardViewModel we would like to instruct the navigation to change the tab in iOS and the same thing to happen on the other platforms.
The only way I've been able to get the tab to change on iOS is to use this.SelectedIndex = 1; from within the iOS ProjectView.
At the moment also the only way I've managed to trigger this change is to fire an event from the DashboardViewModel and then the ProjectViewModel subscribes to this and fires another event which is subscribed to by the ProjectView to instruct it to change the tab in whatever device specific way it needs to. I can't help but think there is a better way to do this.
I've tried taking a look at a custom ViewPresenter for iOS and calling ShowViewModel FirstListViewModel from within the DashboardViewModel but the presenter doesn't appear to be getting used so we just transition normally. My idea was I could get in the middle, cancel the navigation request and then flip the active tab on the ProjectView.
Any suggestions would be appreciated on how we could do this in a better cross platform way using MVVMCross to handle the change if at all possible.
You should be able to do this in any of several ways:
using a custom presenter with overridden Show as you suggest
using a custom presenter with overridden ChangePresentation - and using a custom hint
using a custom binding or a binding to a property within the ProjectView to drive the transition
using a custom IMvxInteraction property
using a custom event from VM to View
using a messenger to send a message from the ViewModels to the Views.
Ultimately lots of these could work and which of these I might choose would depend on which one worked and which one the team are happy with - shipping the working app is always the ultimate goal.
Given where I am with MvvmCross experience, I'd probably opt today for trying the approach of trying a custom IMvxInteraction property. But this might not be for everyone... it certainly might be overkill for this sample...
However, to do this, I would try:
add a public enum Display { Dash, First, Second } to the Core project
add a ProjectViewModel property:
private MvxInteraction<Display> _display = new MvxInteraction< Display >();
public IMvxInteraction<Display> DisplayChange { get { return _display; } }
whenever this ViewModel wants to fire the change it can fire it using e.g. _display.Raise(Display.First)
the ProjectView could then bind Display to its own property which might be implemented like:
private IDisposable _subscription;
private IMvxInteraction<Display> _displayInteraction;
public IMvxInteraction<Display> ChangeDisplay
{
get { return _displayInteraction; }
set
{
if (_subscription != null)
{
_subscription.Dispose();
_subscription = null;
}
_displayInteraction = value;
if (_displayInteraction != null)
{
_subscription = _displayInteraction.WeakSubscribe(DoDisplayChange);
}
}
}
private void DoDisplayChange(Display which)
{
// change the tab display here
}
the binding would be added in ViewDidLoad like:
set.Bind(this).For(v => v.ChangeDisplay).To(vm => vm.DisplayChange);
I have a list on my view model that contains an object and property that I am trying to bind to from the main view.
var field = new UITextField();
Add(field);
this.AddBindings(
new Dictionary<object, string>()
{
{ field, "Text Names[0].Value" }
}
);
This will load fine and display the initial value from the view model but won't receive any values back when UITextField.Text is modified. It seems like it is not 2 way. Value is not a notification property but could be made into one if that is what this setup requires.
I also tried the following but that does work at all:
set.Bind(field).To(vm => vm.Names[0].Value);
Using MvvmCross 3.0.9. Xamarin.iOS 6.3.7
I've just tested this using 3.0.9 with a ViewModel which has an ObservableCollection of non-INPC Thing objects and this two way binding seems to work OK for me - both when the ObservableCollection changes and when the UITextField value changes because of user action.
Can you provide any more of your ViewModel nad list object code? (If not, can you reproduce the error in a simple sample?)
Can you provide any error trace you are seeing (in debug|output)? (This may need enabling - see MvvmCross Mvx.Trace usage)
Can you provide any more information on the form that "does work at all" - this might be a clue about what is going wrong.
I have a problem that the ViewWillAppear method for a UIView does not fire when the application returns from the background. This is a problem, as my main application screen is showing values that are retrieved from the user settings, and if the user has changed these while the application was in the background I need to have the screen refreshed. I have read that one should register for the UIApplicationWillEnterForegroundNotification using NSNotificationCenter.
How do you do this in MonoTouch? Or does anyone know an alternate way of ensuring that the screen is always kept up to date, even when returning from the background?
You could try something along the lines of:
//Register for the notification somewhere in the app
NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillEnterForegroundNotification, EnteredForeground);
//snip
void EnteredForeground (NSNotification notification)
{
// do your stuff here
}
Bear in mind you would need to do this for every view controller you'd like to update when enterting from the background!
I have a UISplitViewController which has a UINavigationController in the master and a UIViewController in the detail. When the device is orientated into landscape mode I want the normal behaviour to be preserved. I.e. The master gets shown in landscape and hidden in portrait.
However depending what the user clicks in the master depends on which UIViewController is loaded into the detail part of the UISplitViewController. What I would like is for the master to be hidden in landscape mode when a user clicks on a button in the detail UIViewController. The problem is I can't get this to work.
My delegate looks like this (have removed some lines for simpler viewing):
public class SplitControllerDelegate : UISplitViewControllerDelegate {
SplitViewController incomingController;
private bool hideMaster = false;
public override bool ShouldHideViewController (UISplitViewController svc,
UIViewController viewController,
UIInterfaceOrientation inOrientation) {
return hideMaster;
}
public void SetHideMaster(bool value) {
hideMaster = value;
}
}
I then call it from the detail UIViewController like
splitControllerDelegate.SetHideMaster(value);
However nothing changes. I'm unsure of how to make it perform the change? Should the master disappear immediately? What causes the WillHideViewController to fire?
Thanks
Mike
What you're trying to do cannot be done officially. ShouldHideViewController() is called only upon device rotation. So unless you rotate forth and back, your controller won't disappear.
You have various options:
Don't use UIListViewController but some other third party replacement
Use UIViewController containment feature of iOS5 and implement your own split view
Apply a hack to UISplitViewController
About the last point. You should be able to force ShouldHideViewController() being called if you set the Delegate property to NULL and then assign a new delegate. Afterwards, call the WillRotate() method of the split view controller using the current orientation.
I'd go for the 2nd option.
By design you cannot do much with the standard UISplitView, try that third party control :
https://github.com/mattgemmell/MGSplitViewController