Xamarin forms, Pull to refresh listView in UWP - win-universal-app

How to refresh a list with Xamarin forms when running on Windows desktop?
It seems we can't pull to refresh.
Tks.
François

Pull to refresh in a ListView on Xamarin Forms requires you to implement these 3 things.
IsPullToRefreshEnabled="True" RefreshCommand="{Binding RefreshListCommand}" IsRefreshing="{Binding IsBusy, Mode=OneWay}"
If you have those 3 things, PullToRefresh will work.
However I have been looking at the code for UWP and can not find anywhere how Xamarin Forms implements PullToRefresh for either WinRT or UWP. Looking at the documentation, WinRT is not supported and hence I assume UWP also wouldn't be supported at this time.
https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/interactivity/#Pull_to_Refresh
Only WP8SL, iOS and Android have PullToRefresh supported at this moment in time.

Try it. Worked for me.
<ListView ItemsSource="{Binding MyList}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}" />
Set IsPullToRefreshEnabled=”True” to enable the functionality, then create these 2 properties in your ViewModel.
private bool _isRefreshing = false;
public bool IsRefreshing {
get { return _isRefreshing; }
set {
_isRefreshing = value;
OnPropertyChanged(nameof(IsRefreshing));
}
}
public ICommand RefreshCommand
{
get {
return new Command(async () =>
{
IsRefreshing = true;
await RefreshData();
IsRefreshing = false;
});
}
}
Now when you pull down from the top of the listview, it will show a refresh animation, while IsRefreshing=”true”.
Example

Related

Switch vs toggle

I'm trying to decide whether to use a switch or toggle for setting an alarm I'm my android application. On fairly new to android and don't know or quite understand all the ins and outs of the frame work. What would be the disadvantages of choosing to trigger the alarm with a switch over a toggle, or vice versa? Is there a slide toggle available in android framework?
The first thing you need to keep in mind is since which API do you want to compile your app?
Toggle Buttons are available since API 1 and Switches are only available since API 14.
Besides that is just a simple decision, which one is the best option for user interface/design
In my opinion Switches give a clear indication of what is currently selected.
Is there a slide toggle available in android framework?
Yes a switch can work as a slide toggle.
The code is very simple, you can basically use the same thought for these two buttons.
Here is an example of a Switch Button
btnSwitch = (Switch) findViewById(R.id.switch_1);
btnSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
if (isChecked) {
Log.i("Switch", "ON");
} else {
Log.i("Switch", "OFF");
}
}
});
Here's an example of a toggle Button
btnToggle = (ToggleButton) findViewById(R.id.toggle_1);
btnToggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Log.i("Toggle", "ON");
} else {
Log.i("Toggle", "OFF");
}
}
});

MvvmCross and UIButton.Selected UISegmentedControl Bindings, iOS

In a cross platform Xamarin app built with the MvvmCross framework I'm using a ToggleButton Widget in an Android .axml layout. I've bound the Checked property to a View Model property using a converter using the following binding syntax:
Checked MarketBuySellViewModel.Direction, Converter=DirectionBool, ConverterParameter='Sell'
Everything works well. On the iOS side, it appears you can use UIButton as a ToggleButton by using the Selected property. This implies that the following binding should achieve what I want on iOS:
set.Bind (SellButton).For(b => b.Selected).To (vm => vm.MarketBuySellViewModel.Direction).WithConversion("DirectionBool", "Sell");
I don't get any binding errors in the application output but the binding itself doesn't seem to work. Clicking the button doesn't set the Direction property and setting the direction to a different value does not set the Selected property on the UIButton.
Do I need to create a Custom Binding or am I simply setting up the binding incorrectly?
I also tried using a UISegmentedControl to achieve the same effect. Is binding to this control supported at all in MvvmCross? I don't see any reference to it in the source code. Does this mean I need to create custom bindings for it too?
For the UIButton, I don't believe there's any included Selected binding built into MvvmCross. Because of this - and because Selected doesn't have a simple paired event SelectedChanged, then I believe Selected binding should work one-way (from ViewModel to View) but not two-way.
There is a binding for the On of a UISwitch control and that's the control I've seen used most in these situations.
If you wanted to add a custom 2-way binding for Selected then I guess you'd have to do this using the ValueChanged event (but would need to check that is correct).
To do so, you'd just build a target binding something like:
public class MvxUIButtonSelectedTargetBinding : MvxPropertyInfoTargetBinding<UIButton>
{
public MvxUIButtonSelectedTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var view = View;
view.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = View;
if (view == null)
return;
FireValueChanged(view.Selected);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var view = View;
if (view != null)
{
view.ValueChanged -= HandleValueChanged;
}
}
}
}
and this could be registered in Setup in protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry) using something like:
registry.RegisterPropertyInfoBindingFactory(typeof(MvxUIButtonSelectedTargetBinding), typeof(UIButton),
"Selected");
Similarly, I don't believe anyone has added a two way UISegmentedControl binding yet - but would happily see one added.
Building a two way UISegmentedControl binding would be quite straight-forward - you'd just have to bind to the pair SelectedSegment and ValueChanged - with code similar to above.
Alternatively, you could switch to using a custom MySegmentedControl which had a nicer Value`ValueChanged` pair which would automatically work without a custom binding - e.g.:
public class MySegmentedControl : UISegmentedControl
{
// add more constructors if required
public int Value
{
get { return base.SelectedSegment; }
set { base.SelectedSegment = value; }
}
}
If any or all of these custom bindings are needed, then the Mvx project is happy to get these bindings added as issues or pull requests along with test/demo UIs in the https://github.com/slodge/MvvmCross-Tutorials/blob/master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs project
Could be helpful to someone else, so i'm sharing my experience. I needed a two way binding for UISegmentedControl.SelectedSegment property to a ViewModel. The one way biding (ViewModel => View) works by default. I couldn't able to properly utilize the solution proposed by Stuart - to subclass the UISegmentedControl. I tried to ensure that the linker does not rip off the new custom control code, but this didn't help me a bit. So a perfectly viable solution is the one with MvxPropertyInfoTargetBinding. Here is the code working ok for me:
public class MvxUISegmentedControlSelectedSegmentTargetBinding : MvxPropertyInfoTargetBinding<UISegmentedControl>
{
public MvxUISegmentedControlSelectedSegmentTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
this.View.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = this.View;
if (view == null)
{
return;
}
FireValueChanged(view.SelectedSegment);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var view = this.View;
if (view != null)
{
view.ValueChanged -= HandleValueChanged;
}
}
}
}
public class Setup : MvxTouchSetup
{
...
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterPropertyInfoBindingFactory(typeof(MvxUISegmentedControlSelectedSegmentTargetBinding), typeof(UISegmentedControl), "SelectedSegment");
}
}

Supporting two storyboards

I have an app with a medium-sized storyboard, which is complicated enough for me not to want to mess around with it too much.
I want to copy this storyboard and change the color scheme and let the user select which color scheme to use.
My question is: can I programmatically select which storyboard will be used by default on startup? If yes - how do I do that?
I looked at a somewhat related question: Storyboards Orientation Support in Xcode 4.5 and iOS 6.x ?
Based on that code I made an extension method:
static bool IsStoryboardLoading {get;set;}
public static T ConsiderSwitchingStoryboard<T> (this UIViewController from) where T: UIViewController
{
if (!IsStoryboardLoading && LocalStorage.Instance.IsWhiteScheme && false) {
try {
IsStoryboardLoading = true;
UIStoryboard storyboard = UIStoryboard.FromName ("MainStoryboard_WHITE", NSBundle.MainBundle);
T whiteView = storyboard.InstantiateViewController (typeof(T).Name) as T;
from.PresentViewController (whiteView, false, null);
return whiteView;
} finally {
IsStoryboardLoading = false;
}
}
return null;
}
}
and then I use it in ViewDidAppear override:
public override void ViewDidAppear (bool animated)
{
this.ConsiderSwitchingStoryboard<MyViewController> ();
}
This code works in some cases but in others it causes an error when performing a push segue:
NSGenericException Reason: Could not find a navigation controller for segue 'segSearchResults'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.
at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSendSuper_IntPtr_IntPtr (intptr,intptr,intptr,intptr)
It might be simpler to just use 1 Storyboard and have 2 sets of controllers in the same storyboard. Just use different storyboard ids for the controllers. You can use the same class on those if needed.
For example:
var whiteController = Storyboard.InstantiateViewController("MyWhiteController") as MyController;
var blueController = Storyboard.InstantiateViewController("MyBlueController") as MyController;
Both could create an instance of MyController, but pull out different layouts from the same storyboard file.
Another option is to use UIAppearance to dynamically set a "style" on all controls of a certain type in your app.
For example, to set the default UIBarButtonItem image throughout your app:
UIBarButtonItem.Appearance.SetBackgroundImage(UIImage.FromFile("yourpng.png"), UIControlState.Normal, UIBarMetrics.Detault);
(You might check my parameters there)

Orientation sensitive iOS App with MonoTouch

I'm currently trying to build an iOS app which is orientation sensitive - when I rotate the app, I want the view to change.
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
new UIAlertView("DEBUG", "test", null, "OK", null).Show ();
// Return true for supported orientations
if (UserInterfaceIdiomIsPhone) {
return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
} else {
return true;
}
}
I inserted the UIAlert to test if this is actually detected, but unfortunately not. I was wondering if I may get any advice on this please?
Apple changed the rotation api in ios6 - see Monotouch.Dialog IOS 6 Split view Rotation issue for some more help (including some MonoTouch)

How do I specify a view to be pushed as Modal in MvvmCross?

I have a view in a MonoTouch app using MvvmCross framework that I would like displayed Modal (NavigationController.PresentModalViewController).
MvvmCross starts from the premise that all ViewModels are just "normal pages" - so in iOS/MonoTouch that means UIViewControllers presented using a UINavigationController.
To move away from this premise - towards tabbed displays, modal displays, split controllers, popups, etc - then you can adjust the Presenter logic within your MonoTouch app.
The presenter's job is to implement:
public interface IMvxTouchViewPresenter
{
void Show(MvxShowViewModelRequest view);
void Close(IMvxViewModel viewModel);
void CloseModalViewController();
void ClearBackStack();
bool PresentModalViewController(UIViewController controller, bool animated);
void NativeModalViewControllerDisappearedOnItsOwn();
}
The presenter used for your app is selected in AppDelegate construction - e.g. see how the TwitterSearch builds different presenters for iPhone and iPad.
Fortunately, for simple Modal support, one of the standard presenters available is MvxModalSupportTouchViewPresenter.cs
This presenter looks to see if the view being presented has the IMvxModalTouchView marker interface - it tests view is IMvxModalTouchView. If this interface is present, then it uses modal presentation for the view instead of "normal navigation".
To use this, change your AppDelegate code to something:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
window = new UIWindow(UIScreen.MainScreen.Bounds);
// initialize app for single screen iPhone display
var presenter = new MvxModalSupportTouchViewPresenter(this, window);
var setup = new Setup(this, presenter);
setup.Initialize();
// start the app
var start = this.GetService<IMvxStartNavigation>();
start.Start();
window.MakeKeyAndVisible();
return true;
}
Then add the marker interface to your modal View(s):
public class MyView : MvxBindingTouchViewController<MyViewModel>, IMvxModalTouchView
{
// ....
}

Resources