Xamarin not updating bindings when page is in background - xamarin

I have a viewmodel bound to a page. The viewmodel is updating a property reacting to an event. When the page in is in background (covered by other pages) it doesn't update its UI, even when i execute the viewmodel code on UI thread:
Device.BeginInvokeOnMainThread(() =>
{
MyProperty = false;
}
Observing this on Android at the moment.
Solved but my own answer below.

If i add a single line to this, it works, the page UI gets updated in background:
Device.BeginInvokeOnMainThread(async() =>
{
await Task.Delay(10);
MyProperty = false;
}

Related

Xamarin Community Toolkit TabView - Navigate within Tabs

For the bottom navigation bar, I'm using a Tabbed Page, and inside of a Tabbed page, I'm using a Tabview from the Xamarin Community Toolkit. On each XCT tab, I'm loading a list of items using the collection view (Xamarin Community Toolkit TabView).  I need to click an item in collection view and  move to another page (detail page) within the same tab of the tabbed page. Although I am aware that Shell might be used, I prefer to use the method described above.
You can use the SelectionChangedCommand to bind with the ItemSelectedCommand command and then use Navigation.PushAsync(new DetailPage()); to navigate to the detail page as Jason suggested.
Here's the code snippet below for your reference:
INavigation Navigation => Application.Current.MainPage.Navigation;
public ICommand ItemSelectedCommand
{
get
{
return new Command(async () =>
{
if (SelectedItem == null) return;
if(SelectedItem.Id ==1)
{
await Navigation.PushAsync(new DetailPage());
}
//else if
SelectedItem = null;
});
}
}

Xamarin CollectionView scroll to bottom at initialization

How do I make sure that a CollectionView displays the last item i.e. the bottom one, from the start without the user having to scroll all the way down.
I use this in a chat UI that I created and want to make sure that the latest messages are in user's view right from the beginning and the user can always scroll up to see older messages.
Set a command in your VM that you can execute when the data is loaded or changed and listen for it in the view and do the scrolling there.
In your VM:
public Command CollectionUpdatedCommand { get; set; }
And then, once the collection changes, whenever you need to fire it:
CollectionUpdatedCommand?.Execute(null);
In your view, set the scroll code to execute when the command is executed:
viewModel.CollectionUpdatedCommand = new Command(() =>
{
Device.BeginInvokeOnMainThread(() => {
MessageList.ScrollTo(viewModel.Messages.Last(), null, ScrollToPosition.End, true);
});
});
You can do something like this along the OnAppearing() :
Device.BeginInvokeOnMainThread(() => {
MessageList.ScrollTo(viewModel.Messages.Last(), null, ScrollToPosition.End, true);
});`
Where MessageList - it's your CollectionView
and
viewModel.Messages - it's your Messages collection for this CollectionView e.g. ObservableCollection

Event handler ordering in Xamarin

I have a list view that I am popping up in Xamarin forms, that I want to hide if someone taps outside of the box. I have a tap gesture recognizer on the parent layout for the list view that handles that. In Android, it all works good. If I click off, it closes, but if I click on an element in the list view, it properly selects it. In iOS, the opposite happens. The gesture handler on the layout fires first and closes the list view without properly selecting the item.
So my question, is there a way to change the order on how the events are fired? If not, is there a better alternative to how I'm trying to accomplish this? Thanks!
If you are using ListView.ItemSelected or ListView.ItemTapped then I ran into the exact same issue the other day. The fix for me was to not use either of those and instead attach a TapGestureRecognizer to the ViewCell that is within the ListView. I also added an IsSelected property to the object that the ViewCell is being bound to so that I could change the background color of the item once it has been clicked.
public class SomePage : ContentPage {
private SomeModel _selectedModel; //It would be best to put this into your ViewModel
...
public SomePage() {
ListView list = new ListView {
ItemTemplate = new DataTemplate(() => {
ViewCell cell = new ViewCell {
View = new ContentView()
};
cell.View.GestureRecognizers.Add(new TapGestureRecognizer {
Command = new Command(() => {
if(_selectedModel != null) { _selectedModel.IsSelected = false; }
SomeModel model = (SomeModel)cell.BindingContext;
model.IsSelected = true;
_selectedModel = model;
})
}
return cell;
}
}
}
}

Xamarin forms background image for all Pages

It´s possible to set an image to be the background of all Pages on my application (for all platforms IOS, Android and WP) ?
Page has a BackgroundImage property, so I can create a base page, set the background and make all my pages extends from it.
I want to know if there is a more appropriate solution, to handle this.
You could use Styles in your App.cs :
public App ()
{
Application.Current.Resources.Add(new Xamarin.Forms.Style(typeof(Page)){
Setters = {
new Xamarin.Forms.Setter { Property = Page.BackgroundImageProperty, Value = "back.png"},
}
});
}
much less preferred or advised but for the sake of showing another option you could attach an event handler to your NavigationPages and set the background from there:
yourRootNavigationPage.Pushed+= (sender, e) => e.Page.BackgroundImage = "back.png";

No text in textbox on save

View:
TextBox x:Name="feedback" Text="{Binding FeedbackText,Mode=TwoWay}"
ViewModel:
public string FeedbackText
{
get
{
return _feedbackTextProperty;
}
set
{
_feedbackTextProperty = value;
RaisePropertyChanged(FeedbackTextPropertyName);
}
}
I am using a bindable application bar but when I click the button there is no value in the FeedbackText property. It looks as if "lostfocus" is not firing to update the property.
I am using MVVM Light. Have I missed something?
If you still had focus in the textbox when you clicked the app bar button the textbox won't fire the lost focus event and cause teh binding to update.
Yes, this can be frustrating. :(
There are various work arounds such as forcibly updating the binding in such a situation or the Binding Helper in the Coding4Fun Tools.
I hope that I am not too late. I had the same problem using Window Phone 8 saving the TextBox text when pressing an ApplicationBarIconButton. A way to fix this issue is to update the binding source property of the focused TextBox. You can do that with the following code:
var focusedObject = FocusManager.GetFocusedElement() as TextBox;
if (focusedObject != null)
{
var binding = focusedObject.GetBindingExpression(TextBox.TextProperty);
if (binding != null)
{
binding.UpdateSource();
}
}
Best!

Resources