Adding items in a List View – Part 5 – Writing a Xamarin.Forms app

 

Last blog post discussed editing items. This blog post uses the MessagingService in Xamarin.Forms to tell the ObservableCollection to add a new item.

To follow along, here’s the diff for this post.

What I learned

  • It’s okay to use the MessagingCenter even in a MVVM pattern. At first I didn’t think this was correct, even though the MessagingCenter appears in the Xamarin documentation under MVVM for adding a new item on a ListView. Obviously I have trust issues.
  • The observable collection updates when its .Add() is called.

Add a footer in the Page1.xaml for the Add button

               <ListView.Footer>
                    <ContentView>
                        <Button Text="Add Fabric" FontSize="Large" Command="{Binding AddFabricCommand}" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
                    </ContentView>
                </ListView.Footer>

Then in the PageOneViewModel, add the command property

public ICommand AddFabricCommand { get; private set; }

and in the constructor, create a command to bind to.

AddFabricCommand = new Command(AddFabric);

and now finish up with the delegate

        private async void AddFabric()
        {

            Fabric fabric = null;
            await this.Navigation.PushAsync(new ItemDetailsPage(fabric));
        }

Now we need to update the ItemDetailsViewModel constructor to handle a new fabric, i.e. if a fabric passed in is null

first we need a property to know if we’re adding  a new fabric or editing an older one.

private bool isNew = false;

now for the constructor

public ItemDetailsViewModel(INavigation Navigation, Fabric fabric)
        {
            isNew = fabric == null;

            if (isNew)
            {
                this.Fabric = new Fabric(Name: "", Seconds: 60);
                Title = "Hello from new item";
            }
            else
            {
                this.Fabric = fabric;
                Title = "Hello from Item " + Fabric.Name;
            }

            this.Navigation = Navigation;
            DoneEditingCommand = new Command(DoneEditing);
        }

Now run the app. You’ll see the familiar ItemDetailsPage appear for the Add, but nothing changes in the ListView. What’s going on?

where's fabric 4

This is because the OCFabric.Add() is never called, so the ObservableCollection can’t add the new Fabric.

Where MessagingService steps in…

When we’re done editing, we need to know whether this is a new fabric or editing an older one so the ObservableCollection can add it.

        private async void DoneEditing()
        {
            if (isNew) {
                MessagingCenter.Send<ItemDetailsViewModel, Fabric>(this, "added", this.Fabric);
            }

            await Navigation.PopAsync();
        }

and now for the receiver. We’re going to subscribe to the message in the PageOneViewModel constructor.

            MessagingCenter.Subscribe<ItemDetailsViewModel, Fabric>(this, "added", (sender, arg) =>
            {
                OCFabrics.Add(arg);
            });

and now Fabric4 is added to the ListView

TheresFabric4.png

Note: yeah I know there’s a more “pure” way to use the MessageCenter by creating a class called FabricSaveMessage as the sender, but it hasn’t really clicked yet why I’d want to create another class. Perhaps further on as I develop this app I’ll run into a good reason for not using the ViewModels as the sender and receiver for these messages.

Alrighty! Next blog post begins my real lightbulb moments using MVVM – how to use a “service” to handle being the “source of truth” for the fabric list.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s