Xamarin.Meetup – Boston Meetup Today: DevOps for Mobile Apps with Dan Hermes

Join us at Microsoft’s NERD Center to learn about DevOps for Mobile Apps! Meet with some of the local Xamarin MVPs and employees while also enjoying some food.

https://www.meetup.com/bostonmobiledev/events/244933704/

How do we keep our iOS and Android builds organized, tested, and distributed to team members and users who need them, with the correct versions flowing into the app stores? This is DevOps for mobile apps.

Dan Hermes, Xamarin MVP and co-organizer of Boston Mobile C# Developers Group, will discuss the high points of his upcoming edX video course for Microsoft on how to do all of these things using Visual Studio Mobile Center (VSMC). He will talk about developing, deploying and managing mobile applications in DevOps environments. He’ll cover setup and management of VSMC and the testing and deployment of mobile apps. Mobile Center Build, Test, and Distribute are powered by Visual Studio Team System (VSTS), Xamarin Test Cloud, and HockeyApp.  Learn the VSMC workflows that tie all of these tools together.

This talk is for any and all native app developers, not just C#.  Many features of VSMC work for Objective-C and Java just as well as Xamarin.

About the Speaker

Dan Hermes is a Xamarin MVP,  Microsoft MVP, and founder of Lexicon Systems, an award-winning Xamarin consulting firm. Mr. Hermes helps developers create great mobile apps and helps businesses develop a winning mobile strategy. His firm’s Xamarin projects include B4UFLY, a drone app for the Federal Aviation Administration, and a cross-platform app for Thermo Fisher Scientific which won a W3, a Davey award, and was a finalist for a Xammy award. Mr. Hermes’ clientele includes dozens of software-building firms such as Fidelity Investments, EDS, and Computerworld Magazine. He has spoken recently at Microsoft Ignite, IBM InterConnect, Microsoft Azure Day, Xamarin DevDays, and mobile user groups nationwide . His mobile cross-platform dev blog is http://mobilecsharpcafe.com/. Connect with him on Twitter at @danhermes. Dan is a writer for MSDN Magazine, a video course instructor for Microsoft’s OpenEdX curriculum, and author of the best-selling Apress book Xamarin Mobile Application Development.

 

 

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisements

Xamarin.Forms Floating Action Button NuGet Announcement

As promised, here is another release of one of my GitHub libraries for Xamarin! This time we are talking about the FloatingActionButton or “FAB”!

Here are some important links:

GitHub project: https://github.com/SuavePirate/Xamarin.Forms.Controls.FloatingActionButton
NuGet package: https://www.nuget.org/packages/SuaveControls.FloatingActionButton

Don’t forget to read up on my original post on how to create your own FloatingActionButton and how to use it: Xamarin.Controls – Xamarin.Forms FloatingActionButton (including iOS!)

Documentation


Xamarin.Forms.Controls.FloatingActionButton

A custom view to create a FloatingActionButton for both Android and iOS as part of Material Design

That’s right, even on iOS!

How to use

Clone the repository and open include the src projects in your Xamarin.Forms and Platform projects.

Now Available on NuGet!

Install-Package SuaveControls.FloatingActionButton

Special note for iOS: Make sure to call FloatingActionButtonRenderer.InitRenderer(); in your AppDelegate.cs in order to avoid linking it out.

Then you can include it in your XAML or call it from C# (See the example projects for a demo):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SuaveControls.FabExample"
             xmlns:controls="clr-namespace:SuaveControls.Views;assembly=SuaveControls.FloatingActionButton"
             x:Class="SuaveControls.FabExample.MainPage">
    <StackLayout Margin="32">
        <Label Text="This is a Floating Action Button!" 
           VerticalOptions="Center" 
           HorizontalOptions="Center"/>

        <controls:FloatingActionButton x:Name="FAB" HorizontalOptions="CenterAndExpand" WidthRequest="50" HeightRequest="50"  VerticalOptions="CenterAndExpand" Image="ic_add_white.png" ButtonColor="#03A9F4" Clicked="Button_Clicked"/>
    </StackLayout>
</ContentPage>

Android Example

Android Floating Action Button

iOS Example

iOS Floating Action Button

TODO:

  • Make it more flexible. Add Different color states, add sizing adjustments, etc.
  • Create UWP implementation
  • Create Xamarin Component

Come support the project and join the contributors list! We would love to see this TODO list dropped to nothing!

 

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Forms BadgeView NuGet Announcement!

As promised, here is another release of one of my GitHub libraries for Xamarin! This time we are talking about the BadgeView​!

Here are some important links:

GitHub project: https://github.com/SuavePirate/BadgeView
NuGet package: https://www.nuget.org/packages/BadgeView

Don’t forget to read up on my original post on how to create your own BadgeView and how to use it: Xamarin.Controls – BadgeView

Documentation

 


BadgeView

A simple Xamarin.Forms control to display a round badge

Now available on nuget! https://www.nuget.org/packages/BadgeView

Installation

Install-Package BadgeView

Usage

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:badge="clr-namespace:BadgeView.Shared;assembly=BadgeView.Shared" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="BadgeViewExample.BadgePage">
    <ContentPage.Content>
        <StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
            <Label HorizontalTextAlignment="Center" Text="Look at me!" />
            <badge:BadgeView Text="3" BadgeColor="Green" VerticalOptions="Center" HorizontalOptions="End" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

With Bindings

<badge:BadgeView Text="{Binding BadgeNumber}" BadgeColor="{Binding BadgeColor}" VerticalOptions="Center" HorizontalOptions="End" />

Without XAML

var badge = new BadgeView()
{
    Text = "4",
    BadgeColor = Color.Red
};

Additional Resources

Check out my blog post on how to build your own if you want!
https://alexdunn.org/2017/03/15/xamarin-controls-badgeview/

 

// TODO:

I’m still working on adding UWP support, but if you want to help contribute to the repository, please do!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

.NET Flux Toolkit Nuget Announcement

Last week I mentioned that I was going to be publishing some of my GitHub library projects on Nuget to make them easier to integrate into your projects – Here’s the newest library for using the Flux in your .NET applications such as Xamarin, UWP, WPF, WinForms, and even ASP.NET.

Nuget: https://www.nuget.org/packages/FluxToolkit/
GitHub: https://github.com/SuavePirate/FluxToolkit/

Here’s how to get started!

FluxToolkit

A super simple library to enable the implementation of Flux in .NET Applications such as Xamarin, UWP, WPF, and more. It contains some base level Flux components to help you get started with your implementation faster.

What is Flux?

Flux is a design pattern created by Facebook with the purpose of creating robust data-driven UI components and handles the flow of data between components and outward to services.

Components

Flux consists of 4 major components – Stores, Actions, Components, and the Dispatcher

Stores

Stores are responsible for containing and managing data for a single domain or data type. Stores listen to the dispatcher for certain events and use the data from the dispatcher to update their data, handle errors, and then pass that update down to the components that are subscribed to the store.

Actions

Actions are responsible for piping events through the dispatcher. Actions are invoked from Components or from background processes. They can also handle some small business logic such as data mapping or talking to external services.

Components

Components are the UI and UI logic layers. They are responsible for displaying views to the users and for handling user events. They invoke Actions and subsribe to Stores to handle updates to the data.

Dispatcher

A single dispatcher is responsible for the Pub/Sub mechanism of events invoked from Actions. Stores subscribe to events by name through the Dispatcher.

How does it work with MVVM and data binding?

ViewModels can be considered part of the Component layer but are separated from the actual UI/Views. This means that the ViewModels are responsible for invoking Actions, and subscribing to Stores. The Views themselves are only responsible for showing the UI and communicating to the ViewModel.

Getting Started

Install

The FluxToolkit is available on Nuget: https://www.nuget.org/packages/FluxToolkit It has no external dependencies and should work with any .NET Standard library or project including Xamarin, Xamarin.Forms, UWP, WPF, and even WinForms. It has not been used for web application development, but it is compatible with ASP.NET projects.

Install the nuget package with the nuget package manager or via the Package Manager command line:

Install-Package FluxToolkit

Create your Stores

Use the StoreBase class from the FluxToolkit to implement your unique stores for your different data types. It contains a generic Data field based on the TData type you pass into the definition. Now you don’t have to worry about communicating to the dispatcher for pub/sub – simply call the base methods for Subsribe and Unsubscribe.

Ensure that you are not using multiple instances of your Stores, but rather should be using either a Singleton or Inversion of Control with Dependency Injection to pass the implementation of your Store to the Components that require it through the constructor. Constantly creating new Stores can cause memory leaks due to the event subscriptions.

Here’s an example store implementation:

    /// <summary>
    /// Event store for holding and managing todo items
    /// </summary>
    public class TodoStore : StoreBase<ObservableCollection<Todo>>
    {
        /// <summary>
        /// Creates a new store and handles subscriptions to the dispatcher
        /// </summary>
        public TodoStore()
        {
            Subscribe<string>(TodoActionTypes.ADD_TODO);
            Subscribe(TodoActionTypes.DELETE_COMPLETED_TODOS);
            Subscribe<string>(TodoActionTypes.DELETE_TODO);
            Subscribe<Todo>(TodoActionTypes.EDIT_TODO);
            Subscribe(TodoActionTypes.TOGGLE_ALL_TODOS);
            Subscribe<string>(TodoActionTypes.TOGGLE_TODO);

            Data = new ObservableCollection<Todo>();
        }

        /// <summary>
        /// Processes an event from the dispatcher before emitting it.
        /// </summary>
        /// <typeparam name="TData"></typeparam>
        /// <param name="eventType"></param>
        /// <param name="data"></param>
        protected override void ReceiveEvent<TData>(string eventType, TData data)
        {
            try
            {
                Error = null;
                switch (eventType)
                {
                    case TodoActionTypes.ADD_TODO:
                        Data.Add(new Todo
                        {
                            Id = Guid.NewGuid().ToString(),
                            Text = data as string,
                            IsComplete = false
                        });
                        break;
                    case TodoActionTypes.DELETE_COMPLETED_TODOS:
                        var itemsToRemove = Data.Where(t => t.IsComplete);
                        foreach(var item in itemsToRemove.ToList())
                        {
                            Data.Remove(item);
                        }
                        break;
                    case TodoActionTypes.DELETE_TODO:
                        var itemToRemove = Data.FirstOrDefault(t => t.Id == data as string);
                        if (itemToRemove != null)
                            Data.Remove(itemToRemove);
                        break;
                    case TodoActionTypes.EDIT_TODO:
                        var itemToEdit = Data.FirstOrDefault(t => t.Id == (data as Todo).Id);
                        if (itemToEdit != null)
                            itemToEdit.Text = (data as Todo).Text;
                        break;
                    case TodoActionTypes.TOGGLE_ALL_TODOS:
                        var areAllComplete = !Data.Any(t => !t.IsComplete);
                        foreach(var todo in Data)
                        {
                            todo.IsComplete = !areAllComplete;
                        }
                        break;
                    case TodoActionTypes.TOGGLE_TODO:
                        var itemToToggle = Data.First(t => t.Id == (data as string));
                        if (itemToToggle != null)
                            itemToToggle.IsComplete = !itemToToggle.IsComplete;
                        break;

                }
            }
            catch (Exception ex)
            {
                // if something goes wrong, set the error before emitting
                Error = ex.Message;
            }
           
            base.ReceiveEvent(eventType, data);
        }
    }

Create your Actions

Create an Actions class for each of your main data types. These actions will call to the Dispatcher to fire events and will also need to implement IActions in order to properly handle the pub/sub mechanism.

    /// <summary>
    /// Actions to be taken against Todo items
    /// </summary>
    public class TodoActions : IActions
    {
        public void AddTodo(string text)
        {
            Dispatcher.Send<IActions, string>(this, TodoActionTypes.ADD_TODO, text);
        }

        public void DeleteCompletedTodos()
        {
            Dispatcher.Send<IActions>(this, TodoActionTypes.DELETE_COMPLETED_TODOS);
        }

        public void DeleteTodo(string id)
        {
            Dispatcher.Send<IActions, string>(this, TodoActionTypes.DELETE_TODO, id);
        }

        public void EditTodo(string id, string text)
        {
            Dispatcher.Send<IActions, Todo>(this, TodoActionTypes.EDIT_TODO, new Todo
            {
                Id = id,
                Text = text
            });
        }

        public void StartEditingTodo(string id)
        {
            Dispatcher.Send<IActions, string>(this, TodoActionTypes.START_EDITING_TODO, id);
        }

        public void StopEditingTodo()
        {
            Dispatcher.Send<IActions>(this, TodoActionTypes.STOP_EDITING_TODO);
        }

        public void ToggleAllTodos()
        {
            Dispatcher.Send<IActions>(this, TodoActionTypes.TOGGLE_ALL_TODOS);
        }

        public void ToggleTodo(string id)
        {
            Dispatcher.Send<IActions, string>(this, TodoActionTypes.TOGGLE_TODO, id);
        }
        
    }

Define your ActionTypes

For each of your data types, you’ll need to define some ActionTypes which translate to the id or name of the events your Actions are invoking through the Dispatcher.

    /// <summary>
    /// Different types of actions that can be completed within the context of Todo items
    /// </summary>
    public class TodoActionTypes
    {
        public const string ADD_TODO = "add_todo";
        public const string DELETE_COMPLETED_TODOS = "delete_completed_todos";
        public const string DELETE_TODO = "delete_todo";
        public const string EDIT_TODO = "edit_todo";
        public const string START_EDITING_TODO = "start_editing_todo";
        public const string STOP_EDITING_TODO = "stop_editing_todo";
        public const string TOGGLE_ALL_TODOS = "toggle_all_todos";
        public const string TOGGLE_TODO = "toggle_todo";
        public const string UPDATE_DRAFT = "update_draft";
    }

Wire up your Components (with MVVM or without)

Have your components subscribe to the Stores that are appropriate for the data need, and invoke the Actions they need. This is a great place to place inject your Stores and Actions into the constructor of your Componentswhether it is through a ViewModel or an ActivityViewController, or Xamarin.Forms.Page.

    public class TodoListPageViewModel : BasePageViewModel
    {
        private readonly TodoStore _todoStore;
        private readonly TodoActions _todoActions;
        private ObservableCollection<Todo> _items;
        private ICommand _createCommand;
        private ICommand _toggleCommand;
        private ICommand _toggleAllCommand;
        private ICommand _deleteCommand;
        private ICommand _deleteCompletedCommand;
        private ICommand _editCommand;
        private ICommand _populateCommand;

        public ICommand CreateCommand
        {
            get
            {
                return _createCommand ??
                    (_createCommand = new RelayCommand(async () =>
                    {
                        var result = await UserDialogs.Instance.PromptAsync(string.Empty, "New", "Done", "Cancel", "Todo...");
                        if (result.Ok)
                        {
                            _todoActions.AddTodo(result.Text);
                        }
                    }));
            }
        }

        public ICommand EditCommand
        {
            get
            {
                return _editCommand ??
                    (_editCommand = new RelayCommand<Todo>(async (t) =>
                    {
                        var result = await UserDialogs.Instance.PromptAsync(new PromptConfig()
                            .SetText(t.Text)
                            .SetTitle("Edit")
                            .SetOkText("Done")
                            .SetCancelText("Cancel")
                            .SetPlaceholder("Todo..."));
                        if (result.Ok)
                        {
                            _todoActions.EditTodo(t.Id, result.Text);
                        }
                    }));
            }
        }

        public ICommand ToggleCommand
        {
            get
            {
                return _toggleCommand ??
                    (_toggleCommand = new RelayCommand<Todo>((t) =>
                    {
                        _todoActions.ToggleTodo(t.Id);
                    }));
            }
        }

        public ICommand ToggleAllCommand
        {
            get
            {
                return _toggleAllCommand ??
                    (_toggleAllCommand = new RelayCommand(() =>
                    {
                        _todoActions.ToggleAllTodos();
                    }));
            }
        }

        public ICommand DeleteCommand
        {
            get
            {
                return _deleteCommand ??
                    (_deleteCommand = new RelayCommand<Todo>((t) =>
                    {
                        _todoActions.DeleteTodo(t.Id);
                    }));
            }
        }

        public ICommand DeleteCompletedCommand
        {
            get
            {
                return _deleteCompletedCommand ??
                    (_deleteCompletedCommand = new RelayCommand(() =>
                    {
                        _todoActions.DeleteCompletedTodos();
                    }));
            }
        }

        public ICommand PopulateCommand
        {
            get
            {
                return _populateCommand ??
                    (_populateCommand = new RelayCommand(() =>
                    {
                        for(var i = 1; i < 20; i++)
                        {
                            _todoActions.AddTodo($"New Item {i}");
                            Task.Delay(200);
                        }
                    }));
            }
        }

        public ObservableCollection<Todo> Items
        {
            get
            {
                return _todoStore.Data;
            }
        }

        public TodoListPageViewModel(TodoStore todoStore, TodoActions todoActions)
        {
            _todoStore = todoStore;
            _todoActions = todoActions;
            _todoStore.OnEmitted += TodoStore_OnEmitted;
        }

        /// <summary>
        /// Processes events from the todo store and updates any UI that isn't handled automatically
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TodoStore_OnEmitted(object sender, StoreEventArgs e)
        {
            switch (e.EventType)
            {
                case TodoActionTypes.ADD_TODO:
                    if(_todoStore.Error == null)
                    {
                        UserDialogs.Instance.Toast("Item added");
                    }
                    break;
                case TodoActionTypes.DELETE_COMPLETED_TODOS:
                    if (_todoStore.Error == null)
                    {
                        UserDialogs.Instance.Toast("Items deleted");
                    }
                    break;
                case TodoActionTypes.DELETE_TODO:
                    if (_todoStore.Error == null)
                    {
                        UserDialogs.Instance.Toast("Item deleted");
                    }
                    break;
                case TodoActionTypes.TOGGLE_ALL_TODOS:
                    if (_todoStore.Error == null)
                    {
                        UserDialogs.Instance.Toast("Items toggled");
                    }
                    break;
                case TodoActionTypes.TOGGLE_TODO:
                    if (_todoStore.Error == null)
                    {
                        UserDialogs.Instance.Toast("Item toggled");
                    }
                    break;
            }
            if(_todoStore.Error != null)
            {
                UserDialogs.Instance.ShowError(_todoStore.Error);
            }
        }
    }

Contributing

Want to add additional examples or more tooling to help people develop their apps with Flux? Fork this repository and create a pull request!

Additional Resources

 

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Reality, Virtually, Hackathon This Weekend!

Reality, Virtually, Hackathon is this weekend October 6th – 9th at MIT’s Media Labs.

I’m excited to announce that I’ll be joining the Microsoft team to mentor participants at this year’s installment of the hackathon. If you’re working with Microsoft technologies such as using C# with Unity, Hololens, Acer VR, Xamarin with ARKit and ARCore, Xenko,  or using any of the Azure Cloud Services, then I’m here to help. I’m looking forward to working with some incredible teams with some of the latest technology to build some awe inspiring applications.

Check out some of the other mentors there as well!
http://www.realityvirtuallyhack.com/mentors/ 

Here’s the schedule:

Event Schedule


Friday


Saturday


Sunday


Monday

 


I’ll be there from Friday evening until Sunday evening, so keep an eye out for me if you’re around!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Nuget – Coming to a Nuget Package Near You

Your voices have been heard – I’m bringing all my helpful controls and libraries to nuget!

Over the next two weeks, I will be going through each one of my projects and getting them nuget-ready. I’ll then be putting them up on nuget and announcing their individual releases here on my blog.

Here’s what you can expect to see on nuget:

So stay tuned, and if you want to contribute to any of these tools, please fork those repositories!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

HackMIT This Weekend!

HackMIT is this weekend, September 16-17.

I’m happy to announce that I’ll be mentoring as one of the local Microsoft MVPs that were invited to help as part of the Microsoft sponsorship of the event. I look forward to building some incredible applications with some of the brightest students coming to Cambridge, and may the best faction win! Keep an eye out for me Sunday morning, and feel free to reach out if you’re attending.

 

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.