Thursday, September 20, 2012

Baby Learns to Write beta is finished

Today I finished beta version of Baby Learns to Write. You can check out the function and how it looks in this screencast.



In the upcoming version, I will address
  • Advanced navigation
  • More "candy" UI
  • Save the drawing to image

Monday, September 17, 2012

Simple navigation implementation in my first Windows 8 app - Part 2

As in previous post, I described how to implement simple navigation in Baby Learns to Write. Even it worked as expected, but I don't like the implementation when it's not pure MVVM, I still need to add code to code behind file to make the app works. In this post, I will address it.

First, I will update the commands.
    public abstract class MoveCommand : ICommand
    {
        protected readonly MainPageViewModel ViewModel;

        protected MoveCommand(MainPageViewModel viewModel)
        {
            ViewModel = viewModel;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public abstract void Execute(object parameter);

        public event EventHandler CanExecuteChanged;
    }

    public class MoveNextCommand : MoveCommand
    {
        public MoveNextCommand(MainPageViewModel viewModel) : base(viewModel)
        {
        }

        public override void Execute(object parameter)
        {
            ViewModel.MoveNext();
        }
    }

    public class MovePreviousCommand : MoveCommand
    {
        public MovePreviousCommand(MainPageViewModel viewModel) : base(viewModel)
        {
        }

        public override void Execute(object parameter)
        {
            ViewModel.MovePrevious();
        }
    }
The most important thing is CanExecute() always return true, and I removed RaiseCanExecuteChanged() as I don't need it anymore.

Then I update the view model
public class MainPageViewModel : INotifyPropertyChanged
    {
        private readonly List _numbers;
        private int _currentIndex;

        public int Number
        {
            get { return _numbers[_currentIndex]; }
        }

        public ICommand MovePreviousCommand { get; private set; }
        public ICommand MoveNextCommand { get; private set; }

        public MainPageViewModel()
        {
            _numbers = new List {1, 2, 3};

            _currentIndex = 0;

            MovePreviousCommand = new MovePreviousCommand(this);
            MoveNextCommand = new MoveNextCommand(this);
        }

        public bool CanMovePrevious
        {
            get { return _currentIndex > 0; }
        }

        public bool CanMoveNext
        {
            get { return _currentIndex < _numbers.Count - 1; }
        }

        public void MovePrevious()
        {
            if (CanMovePrevious)
            {
                _currentIndex--;

                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
                PropertyChanged(this, new PropertyChangedEventArgs("CanMovePrevious"));
                PropertyChanged(this, new PropertyChangedEventArgs("CanMoveNext"));
            }
        }

        public void MoveNext()
        {
            if (CanMoveNext)
            {
                _currentIndex++;

                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
                PropertyChanged(this, new PropertyChangedEventArgs("CanMovePrevious"));
                PropertyChanged(this, new PropertyChangedEventArgs("CanMoveNext"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
In additional raising the PropterChanged event for Number property, I also raise for CanMovePrevious and CanMoveNext property. These properties are used to bind to the XAML as below
    <StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}" HorizontalAlignment="Center" Orientation="Horizontal" VerticalAlignment="Center">
        </StackPanel>
The last thing I need to do is removing all redundant code from code behind file.
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            DataContext = new MainPageViewModel();
        }

        /// 
        /// Invoked when this page is about to be displayed in a Frame.
        /// 
        /// Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
Now the app is written with pure MVVM.

You can grab the source code from here.

Wednesday, September 12, 2012

Monday, September 10, 2012

Simple navigation implementation in my first Windows 8 app

As mentioned in previous post, I'm working on my first Windows 8 app. In the upcoming beta version, I will introduce simple navigation function. The simple navigation is really simple, the app just provides 2 buttons, Previous and Next, to help the child browse a list of characters and numbers. It also means the Previous button should be disabled when the app is at the first character, and the Next button should be disabled when the app is at the last character. And I will use MVVM pattern (without any supporting from MVVM framework) to implement the function.

To learn how to implement it, I create a sample project instead of doing it directly in the app project. This sample project works the same way as my real project. It provides an UI with 2 buttons to move previous/next, one label to display the number and a list of number to navigate between. Let's start with the UI.
    
        
The most important parts are binding commands and the number to display from the view model.

As applying MVVM pattern, the code behind file for this UI is very simple.
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            DataContext = new MainPageViewModel();
        }

        /// 
        /// Invoked when this page is about to be displayed in a Frame.
        /// 
        /// Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
Now are the commands. I create a abstract MoveCommand which implement ICommand to share CanExecuteChanged and RaiseCanExecuteChanged()
    public abstract class MoveCommand : ICommand
    {
        public abstract bool CanExecute(object parameter);
        public abstract void Execute(object parameter);

        public event EventHandler CanExecuteChanged;

        public void RaiseCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, EventArgs.Empty);
            }
        }
    }
The MoveNextCommand and MovePreviousCommand extend MoveCommand and provide implementation for abstract methods.
    public class MoveNextCommand : MoveCommand
    {
        private readonly MainPageViewModel _viewModel;

        public MoveNextCommand(MainPageViewModel viewModel)
        {
            _viewModel = viewModel;
        }

        public override bool CanExecute(object parameter)
        {
            return _viewModel.CanMoveNext;
        }

        public override void Execute(object parameter)
        {
            _viewModel.MoveNext();

            RaiseCanExecuteChanged();
        }
    }

    public class MovePreviousCommand : MoveCommand
    {
        private readonly MainPageViewModel _viewModel;

        public MovePreviousCommand(MainPageViewModel viewModel)
        {
            _viewModel = viewModel;
        }

        public override bool CanExecute(object parameter)
        {
            return _viewModel.CanMovePrevious;
        }

        public override void Execute(object parameter)
        {
            _viewModel.MovePrevious();

            RaiseCanExecuteChanged();
        }
    }
The last thing is the view model class
    public class MainPageViewModel : INotifyPropertyChanged
    {
        private readonly List _numbers;
        private int _currentIndex;

        public int Number
        {
            get { return _numbers[_currentIndex]; }
        }

        public ICommand MovePreviousCommand { get; private set; }
        public ICommand MoveNextCommand { get; private set; }

        public MainPageViewModel()
        {
            _numbers = new List {1, 2, 3};

            _currentIndex = 0;

            MovePreviousCommand = new MovePreviousCommand(this);
            MoveNextCommand = new MoveNextCommand(this);
        }

        public bool CanMovePrevious
        {
            get { return _currentIndex > 0; }
        }

        public bool CanMoveNext
        {
            get { return _currentIndex < _numbers.Count - 1; }
        }

        public void MovePrevious()
        {
            if (CanMovePrevious)
            {
                _currentIndex--;

                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
            }
        }

        public void MoveNext()
        {
            if (CanMoveNext)
            {
                _currentIndex++;

                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
When MoveNextCommand or MovePreviousCommand is fired, the appropriate method (MoveNext() or MovePrevious()) is called. The method checks if it's possible to move then increase or decrease the index and fire the ProperyChanged event to notify the UI to update the label's text.

Now the app seems looks fine, the buttons should work as expected. But no, there is a problem. When I click Next button, the label's text was updated but the Previous button is still disabled. According to the ICommand document, when the command is bind to the button, the button will call CanExecute() method to check whether the command should or should not be enabled. The Previous button is still disabled because we didn't fire its CanExecuteChanged event yet. To fire the CanExecuteChanged event, I need to update the code as below.
    public sealed partial class MainPage : Page
    {
        private readonly MainPageViewModel _viewModel;

        public MainPage()
        {
            this.InitializeComponent();

            _viewModel = new MainPageViewModel();
            _viewModel.MovePreviousCommand.CanExecuteChanged += MovePreviousCommand_CanExecuteChanged;
            _viewModel.MoveNextCommand.CanExecuteChanged += MoveNextCommand_CanExecuteChanged;

            DataContext = _viewModel;
        }

        void MoveNextCommand_CanExecuteChanged(object sender, EventArgs e)
        {
            if (((CancelEventArgs)e).Cancel)
            {
                return;
            }

            ((MoveCommand)_viewModel.MovePreviousCommand).RaiseCanExecuteChanged(true);
        }

        void MovePreviousCommand_CanExecuteChanged(object sender, EventArgs e)
        {
            if (((CancelEventArgs)e).Cancel)
            {
                return;
            }

            ((MoveCommand)_viewModel.MoveNextCommand).RaiseCanExecuteChanged(true);
        }

        /// 
        /// Invoked when this page is about to be displayed in a Frame.
        /// 
        /// Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }

    public abstract class MoveCommand : ICommand
    {
        public abstract bool CanExecute(object parameter);
        public abstract void Execute(object parameter);

        public event EventHandler CanExecuteChanged;

        public void RaiseCanExecuteChanged(bool cancel)
        {
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, new CancelEventArgs {Cancel = cancel});
            }
        }
    }

    public class MoveNextCommand : MoveCommand
    {
        private readonly MainPageViewModel _viewModel;

        public MoveNextCommand(MainPageViewModel viewModel)
        {
            _viewModel = viewModel;
        }

        public override bool CanExecute(object parameter)
        {
            return _viewModel.CanMoveNext;
        }

        public override void Execute(object parameter)
        {
            _viewModel.MoveNext();

            RaiseCanExecuteChanged(!_viewModel.CanMoveNext);
        }
    }

    public class MovePreviousCommand : MoveCommand
    {
        private readonly MainPageViewModel _viewModel;

        public MovePreviousCommand(MainPageViewModel viewModel)
        {
            _viewModel = viewModel;
        }

        public override bool CanExecute(object parameter)
        {
            return _viewModel.CanMovePrevious;
        }

        public override void Execute(object parameter)
        {
            _viewModel.MovePrevious();

            RaiseCanExecuteChanged(!_viewModel.CanMovePrevious);
        }
    }
Here I use CancelEventArgs instead of EventArgs to stop firing event at the right time. Otherwise it can lead to StackOverflowException.

Now the app works as I expected. When the app starts, the Previous button should be disabled, the Next button should be enabled. When I click Next, the label's text was updated and the Previous button should be enabled. When I move to last item, the Next button should be disabled while the Previous button should be enabled...

Even now the app works as I expected, I don't like this implementation when it's not pure MVVM, I still need to add code to code behind file to make the app works.

In the next post, I will update the code so it will "more MVVM". Stay tuned!

Source code for this post, you can get from here.

Friday, September 7, 2012

My first Windows 8 app

Learn from an Android app of my friend, I decided to implement it on Windows 8. The app was named "Baby Learns to Write" ("Bé yêu học viết" in Vietnamese). Its purpose is helping the children learn how to write single Vietnamese characters and numbers. The child will "draw" the characters and numbers on a Windows 8 tablet's touch screen. The "picture" can be saved or shared.
Here is the road map
Beta:
  • Providing simple navigation between characters and numbers to draw
  • Possible to "draw", of course
  • Possible to select color to draw (black, red, blue or green)
1.0:
  • Providing advanced navigation between characters and numbers
  • The UI looks more "candy" (The app is for children, right? I'm just a developer so I'm not sure how much I can do for designing, but I will try my best)
  • Save as picture
2.0:
  • Providing words to describe the characters (maybe with audio)
  • Share the "picture" via email
3.0:
  • Providing "drawing" instruction by animation (maybe)
The app is not too complicated but I only do it in my spare time. I expect to finish version 1.0 before Windows 8 GA on October 26. If possible, it will available on Windows Store.
More to come.
BTW, thanks Hai for giving the idea and app's resources.