Xaml Formatting and Code Behind (in progress)

Added additional formatting to ContentPage.Content elements. Added x:Name to Label and Switch.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Viand.AddItemPage"
	Title="Add Item">
	<ContentPage.ToolbarItems>
		<ToolbarItem Name="Save"/>
	</ContentPage.ToolbarItems>
	<ContentPage.Content>
		<StackLayout Orientation="Vertical"
			Padding="20,20,20,0"
			Spacing="15">
			<Entry Placeholder="Type your new item here"/>
			<StackLayout Orientation="Horizontal"
				HorizontalOptions="Center"
				VerticalOptions="Center">
				<Label x:Name="destinationLabel">
					Save to Add list
				</Label>
				<Switch x:Name="destinationSwitch"
					IsToggled="true"
					Toggled="OnDestinationSwitchToggled"/>
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Referencing OnDestinationSwitchToggled in code behind.

public partial class AddItemPage : ContentPage
{
	public AddItemPage()
	{
		InitializeComponent();
	}

	void OnDestinationSwitchToggled(object sender, EventArgs args)
	{
		if (destinationSwitch.IsToggled == true) {
			destinationLabel.Text = "Save to Add list";
		} else {
			destinationLabel.Text = "Save to Buy list";
		}
	}
}

Changing label based on switch state with code behind.

Viand-Add-Item-SaveToAdd  Viand-Add-Item-SaveToBuy

Posted in Other, Side Projects | Tagged , , , | Leave a comment

Initial Xaml for Add Item Screen

In less than an hour I was able to add a Forms ContentPage Xaml to my Viand project by right clicking on the Viand project, selecting Add -> New File -> Forms -> Forms Content Page Xaml, and adding the Xaml below to the screen.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Viand.AddItemPage"
	Title="Add Item">
	<ContentPage.ToolbarItems>
		<ToolbarItem Name="Save" />
	</ContentPage.ToolbarItems>
	<ContentPage.Content>
		<StackLayout Orientation="Vertical">
			<Entry></Entry>
			<StackLayout Orientation="Horizontal">
				<Label>Save to Add list</Label>
				<Switch IsToggled="true"></Switch>
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

And here’s the iPhone and Android screens created from that Xaml.

Viand-Add-Item-iOS-1  Viand-Add-Item-Android-1

Remaining tasks to finish this screen:

  • Display keyboard when screen is displayed; keep displayed when switch state changes
  • Change “Save to Add/Buy list” label based on switch state
  • Enabling Save function
  • Formatting screen elements
Posted in Side Projects, Software Development | Tagged , , , | Leave a comment

Adding Items

The penultimate feature is the ability to add new items to the Add list.

Viand-Alphabetized-Add-iOS

My initial idea was to allow you to add a new item to the Add list inline but off the top of my head I can’t think of a way to do it with out-of-the-box Xamarin.Forms (one of it’s minor weaknesses) so I’m thinking a about adding another screen that’s displayed when you tap on the Add button in the upper right corner.

Viand-Add-Screen_2

On this screen to add a new item to a list you type its name in the text field at the top of the screen and then tap Save. By default the new item is added to the Add list but but you can change the destination to the Buy list by tapping the switch below the text field before you tap Save.

Once the item is added to the selected list the text field is cleared but still has focus so you can add another item.

I probably should add some validation in there to prevent adding the same item to both lists.

I think I’m going to try to use Xaml to create this screen (assuming both methods can coexist in the same project).

Posted in Side Projects, Software Development | Tagged , , , | Leave a comment

Alphabetizing Buy

I alphabetized the Buy list items but didn’t refactor the code to add headers or a jump list.

internal void UpdateBuyItemsList()
{
	if (Application.Current.Properties.ContainsKey("Items")) {
		allItems = (List<Item>)Application.Current.Properties["Items"];
		allItems.Sort();
		buyItems = allItems.Where(item => item.Buy != false);
	}

	buyView.ItemsSource = buyItems;
}

I figure this list will always be shorter than the Add list so headers and a jump list should be unnecessary.

Posted in Side Projects, Software Development | Tagged , , | Leave a comment

Alphabetizing Add

Because the Add list had the potential to be much longer than the Buy list I wanted to alphabetize that list’s contents to make it easy to find items, avoiding the “search an unalphabetized list for a particular item, can’t find it so, in frustration, add it again” syndrome that plagued the other list programs my wife and I have been using

The Xamarin.Forms ListView provides several properties to do list grouping–IsGroupingEnabled, GroupDisplayBinding, and GroupShortNameBinding.

addView = new ListView {
	ItemTemplate = new DataTemplate(typeof(AddCell)) { Bindings =  {{ AddCell.TextProperty, new Binding("Name") }}},
	IsGroupingEnabled = true,
	GroupDisplayBinding = new Binding("Title"),
	GroupShortNameBinding = new Binding("Title")
};

The Title binding for the latter two properties comes from ItemCollection, an observable collection of items (or ObservableCollection<Item> in C# parlance).

public class ItemCollection : ObservableCollection<Item>
{
	public string Title { get; set; }

	public ItemCollection(string title)
	{
		Title = title;
	}

	public static IEnumerable<Item> GetSortedAddData()
	{
		List<Item> allItems;

		if (Application.Current.Properties.ContainsKey("Items")) {
			allItems = (List<Item>)Application.Current.Properties["Items"];
			allItems.Sort();
			AddPage.addItems = allItems.Where(item => item.Buy != true);
		}

		return AddPage.addItems;
	}
}

Besides a Title property, ItemCollection has a GetSortedAddData method which performs the similar function to the old UpdateAddItemsList method in AddPage–getting a complete list of allItems from the application’s Properties collection and populating the addItems list with only those items whose Buy property is not equal to true. The only major addition here is that the allItems list is sorted before the Buy == false items are extracted.

In AddPage, the UpdateAddItemsList method has been repurposed. Originally the method returned nothing but merely created a list of items whose Buy property was false and used this list as the ListView’s ItemsSource.

internal ObservableCollection<ItemCollection> UpdateAddItemsList()
{
	var allAddItemGroups = new ObservableCollection<ItemCollection>();

	foreach (Item item in ItemCollection.GetSortedAddData())
	{
		var addItemGroup = allAddItemGroups.FirstOrDefault(g => g.Title == item.Label);

		if (addItemGroup == null)
		{
			addItemGroup = new ItemCollection(item.Label);
			addItemGroup.Add(item);
			allAddItemGroups.Add(addItemGroup);
		}
		else
		{
			addItemGroup.Add(item);
		}
	}
	return allAddItemGroups;
}

Now the method returns an ObservableCollection of item collections where each item collection consists of an ObservableCollection of items. The Title of each of item collection is determined by the labels of the items it contains.

As the method iterates through the addList items, it searches the existing item collections to see if on with the current item’s label exists. If it does, it place the current item in that particular item collection; if it doesn’t, it creates a new item collection, sets its Title equal to the item’s Label, and then adds the current item to the newly created item collection.

When we’ve finished iterating through the entire addList, we’ve got a collection of collections.

Viand-ObservableCollections

Setting the list view’s ItemsSource to this collection of collections and setting the IsGroupingEnabled = true and the GroupDisplayBinding and GroupShortDisplayBinding to each collection’s Title we get an alphabetized list with section headers between each group and, for iOS, a jump list on the right of the screen.

Viand-Alphabetized-Add-iOS  Viand-Alphabetized-Add-Android

 

I’d like just a jump list on iPhone but there doesn’t seem to be an easy way to have a jump list without also having section headers (and what would you do on Android which doesn’t have a jump list concept as part of its user interface). I guess if grouping is enabled, section headers are the minimal user interface required.

 

 

Posted in Side Projects, Software Development | Tagged , , | Leave a comment

Three Context Items

Since I gave the user the ability to increase the quantity of an item on the Buy list by one I wanted to see if I could add another context action that would let them decrease the quantity by one.

You can easily do this by added the following code (the example below is for just the Buy list, Add list would be similar).

// Added to BuyCell
var minusOneAction = new MenuItem { Text = "-1" };
minusOneAction.Clicked += (sender, e) => MessagingCenter.Send<BuyCell>(this, "SubtractOne");

ContextActions.Add(minusOneAction);

// Added to BuyPage constructor
MessagingCenter.Subscribe<BuyCell>(this, "SubtractOne", ItemQuantityDecreased);

// Added to BuyPage class
internal void ItemQuantityDecreased(BuyCell item)
{
	bool alsoUpdateAddList = false;

	if (allItems != null) {
		var obj = allItems.First(x => x.Name == item.Text);
		if (obj != null) {
			if (obj.Quantity != 1) {
				obj.Quantity -= 1;
			} else {
				obj.Quantity = 1;
				obj.Buy = false;
				alsoUpdateAddList = true;

			}
		}
	}

	UpdateBuyItemsList();
	if (alsoUpdateAddList) MessagingCenter.Send<BuyPage>(this, "UpdateAddItemsList");
}

On iOS with the second and any subsequent items being replaced by a More button. Tapping More will display those items in a platform-specific spinner.

Three-Context-Actions-iOS

On Android there’s no hiding of the buttons (at least with three, I don’t know what would happen if they context actions extended off of the left side of the screen.

Three-Context-Actions-Android

I don’t care for the hiding on iOS since it adds a second click but I’ll leave this code in a Git branch in case I decide to include it in the app down the road (trying to get in the habit of trying out new ideas in new Git branches).

Posted in Uncategorized | Leave a comment

Buy Page – ItemBought and ItemQuantityIncreased

Writing the BuyPage code to buy and item (ItemBought) or increase its quantity (ItemQuantityIncreased) was also relatively straightforward.

ItemBought

Again the allItems list is searched for the item whose Bought context action was tapped. When found, it’s Buy property is set to false.

internal void ItemBought(BuyCell item) 
{
	if (allItems != null) {
		var obj = allItems.First(x => x.Name == item.Text);
		if (obj != null) {
			obj.Buy = false;
		}
	}

	UpdateBuyItemsList();

	MessagingCenter.Send<BuyPage>(this, "UpdateAddItemsList");
}

UpdateBuyItemsList is called after the item property is updated. This method refreshes the BuyPage by rebuilding the buyItems list and setting the buyView’s ItemsSource to this rebuilt list. This has the effect of removing the selected item from the Buy list (the code below was out refactored of the BuyPage constructor and into its own method).

internal void UpdateBuyItemsList()
{
	if (Application.Current.Properties.ContainsKey("Items")) {
		allItems = (List<Item>)Application.Current.Properties["Items"];
		buyItems = allItems.Where(item => item.Buy != false);
	}

	buyView.ItemsSource = buyItems;
}

Finally, sending an “UpdateAddItemsList” message calls the list update method in AddPage so the selected item can be added to that list (the Send message is caught by having a corresponding Subscribe message in AddPage that points to its update list method).

MessagingCenter.Subscribe<AddPage>(this, "UpdateBuyItemsList", (sender) => UpdateBuyItemsList());

ItemQuantityIncreased

Like RemoveItem, the effects of ItemQuantityIncreased are limited to the BuyPage screen–the item quantity is increased by one (someone might want to buy two or three of an item).

In order to change an item’s quantity if first has to have one so I added an new Quantity property to the Item class and gave it a default value of one in its constructor is the quantity parameter is left empty when a new item is created.

public class Item
{
	public string Name { get; set; }
	public bool Buy { get; set; }
	public int Quantity { get; set; }

	public Item(string name, bool buy, int quantity = 1 ) {
		this.Name = name;
		this.Buy = buy;
		this.Quantity = quantity;
	}
}

Once again the buyItems list is searched for the item whose +1 context action was tapped. When found, it’s Quantity property incremented by one.

internal void ItemQuantityIncreased(BuyCell item)
{
	if (allItems != null) {
		var obj = allItems.First(x => x.Name == item.Text);
		if (obj != null) obj.Quantity += 1;
	}

	UpdateBuyItemsList();
}

A call to UpdateBuyItemsList refreshes BuyPage, displaying the item’s new quantity.

To display an item’s quantity onscreen, I had to bind its Quantity property to the BuyCell’s DetailProperty in BuyPage’s constructor.

buyView.ItemTemplate.SetBinding(BuyCell.TextProperty, "Name");
buyView.ItemTemplate.SetBinding(BuyCell.DetailProperty, "Quantity");
Posted in Side Projects, Software Development | Tagged , , | Leave a comment