UI | UX By & For Dev : User Focus

UI | UX By & For Dev : User Focus

As a developer, if I need to pick a concept which I find most important in deciding the placement of information, then it is the user focus areas on screen. You want your users to find more important information swiftly so you keep those elements in the areas of the screen which get more focus and keep less important elements in areas which are less intrusive during user scanning the page. Have a look at following imaginary compartmentalization of screen areas:

Sufrace Pro 3 Screen Elements Placement UX UI

Green dots represent user focus. So, 1,2 and 5 are the areas which are going to get most focus of user. Then come 3, 6, and 9. And the least focus grabbing areas are 4, 7 and 8. The arrows show the shifting of user gaze while they are scanning your app’s page. This shifting of gaze is closely related to the focus areas. User’s focus shifts in this sequence (not very strictly but generally)
1 > 2 > 5 > 3 > 6 > 9 > 4 > 8 > 7.

This can be a great guide to plan control/element placement in your app.

Microsoft Visual Layout Guide

C# : Properties and Serialization

Protected by mikecogh, on Flickr
Protected, a photo by mikecogh on Flickr.

Does your app serialize (on IS or for wire-travelling) model entities to JSON/XML? Did you come across a scenario where you want to ensure that a property is, though serialize-able but should not be settable from the code? For example ID property. Your model class creates this ID internally and it also gets serialized. For it being serialize-able, it is required that the properly is public, but then you expose it to other parts of code as well and make it vulnerable for accidental edits. EditorBrowsableAttribute is not the solution here because of two reasons; one it does not work with the code inside your project, second if it did work, it’s still only hiding from IntelliSense and not stopping you from setting the property in code.
I tackle this scenario in my Nokia Lumia app by having a super-class PersistentEntity and then derive all model classes from PersistentEntity class.
ClassDiagram
PersistentEntity has two properties related to serialization – WriteState and ReadState which are of PersistencyStates enumeration type. PersistencyStates enum has following members – None, WritePending, Queued (because all serialization takes place on BG thread), Writing, Written, Read, and Reading. In case of serializing an entity, as soon as any changes made to the object, the object goes in WritePending, and from there it changes state from Queued to Writing, to Written state. Every other property in derived class which needs to be exposed for serialization only, ensures that in setter sets the value SavingState is “Saving”. If it is not, throw an invalid operation exception with proper message. Let’s have a look at the code.

PersistencyStates enumerator:

    public enum PersistencyStates
    {
        None, WritePending, Queued, Writing, Written, Reading, Read
    }

This is the super class PersistentEntity:

   public class PersistentEntity : ISerializable
    {
        [NonSerialized] //for Silverlight this is IgnoreDataMember attribute
        public PersistencyStates WriteState { get; private set; }
        [NonSerialized] //for Silverlight this is IgnoreDataMember attribute
        public PersistencyStates ReadState { get; private set; }

        #region serialization related methods
        [OnDeserializing]
        public void OnDeSerializingEntity(StreamingContext context)
        {
            this.WriteState = PersistencyStates.Writing;
        }
        [OnDeserialized]
        public void OnDeSerializedEntity(StreamingContext context)
        {
            this.WriteState = PersistencyStates.Written;
            //do something else if required
            this.WriteState = PersistencyStates.None;
        }
        [OnSerializing]
        public void OnSerializingEntity(StreamingContext context)
        {
            this.ReadState = PersistencyStates.Reading;
        }
        [OnSerialized]
        public void OnSerializedEntity(StreamingContext context)
        {
            this.ReadState = PersistencyStates.Read;
        }
        #endregion //serialization related methods


        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            //do nothing;
        }
    }

This is the derived class TestEntity have a property ID which is ensured to update only while serialization:

   class TestEntity : PersistentEntity
    {
        private Guid _id = Guid.NewGuid();
        public Guid ID 
        {
            get 
            {
                return _id;
            }
            set
            {
                if (this.WriteState == PersistencyStates.Writing)
                {
                    _id = value;
                }
                else
                {
                    throw new InvalidOperationException("Cannot set ID from outside", new Exception("MyCompany.MVVM.Model.TestEntity.ID has public setter for the purpose of serialization only. Not designed to be set from outside of the class."))
                }
            }
        }
    }

I hope I could make the intent and implementation clear.

XAML|C# Step By Step : UserControl – Wait Spinner

Waiting by moonux, on Flickr
Waiting, a photo by moonux on Flickr.

Something is cooking in the background? Do not forget to inform your user. A modern, flat, light weight, wait spinner is an animated and prominent way to inform user about running background processes (you would not have long running processes on the UI thread, right? See how to effectively free up UI). You would choose to show this control in that area of the screen to which the information, related to which the BG work is taking place – loading/processing etc, belongs. You may have multiple information points on screen for which background work is running.

For this step-by-step we will create this example:

A practical example of implementation of this spinner is this panorama app there are two wait spinners being used, one in Quick Stopwatch pano, and other in Recent pano. When data related to Quick stopwatch is loading, the wait spinner shows beside the title “Quick”, and when data related to Recent is loading, the wait spinner shows near the pano title “Recent”. This way user is informed about which section of the app is doing something in the background.

WaitSpinnerExample

Don’t have this app on your Windows Phone? Visit here

Let’s go through step-by-step of creating a WaitSpinner UserControl and using it in a page.

Step 1 : Create Solution and Project

  1. Create a project in VS with the name “WaitSpinner”. The solution gets created automatically.
  2. Right click on the solution in Solution Explorer, and choose “Add”>”New Project”.
  3. Select Class Library type project and name it “XAMLControls”.

Step 2 : Create UserControl

  1. Right click on XAMLControls and select “Add”>”New item”.
  2. Choose User Control and name it “UCWaitSpinner”.
  3. A new UCWaitSpinner.xaml and its code behind is created.

Step 3 : Open in Blend

Right click on UCWaitSpinner.xaml and choose to open in Blend. Depending on the version of Visual Studio the view you get might be a little different, but most of the UI will be similar. You will get something like this:
01_OpenUCInBlend

Step 4 : Change the type of Layout control

Change the type of Layout from Grid to ViewBox.
02_ChangeLayoutType

Step 5 : Add a new Grid to Layout ViewBox

  1. Choose Grid from control and right click and drag in XAML design view area.
  2. Update Layout properties; Height and Width to 50, HorizontalAlignment and VerticalAlignment to Stretch.

03_AddGridToLayoutRoot

Step 6 : Add Outer border

  1. Choose Ellipse tool from Toolbox and create a circle in the design area. Don’t worry about size and fill at this point.
  2. Make sure Ellipse is selected.
  3. In Properties.Brushes;
    • Set Fill to “No Brush”.
    • Set Stroke to “PhoneForegroundBrush”.
  4. In Layout section;
    • Set HorizontalAlignment to stretch.
    • Set VerticalAlignment to stretch.
    • Set all margins to 0.

04_CreateACircle

Step 7 : Add axis for hands

  1. Choose Ellipse tool from Toolbox again and create a circle in the middle of XAML design. Don’t bother about size at this point.
  2. Make sure this ellipse is selected.
  3. In Properties.Brushes;
    • Set Fill to “PhoneForegroundBrush”.
    • Set Stroke to “No Brush”.
  4. In Layout section;
    • Set Width and Height to 5.
    • Set HorizontalAlignment to center.
    • Set VerticalAlignment to center.
    • Set all margins to 0.

05_CreateAxisForHands

Step 8 : Add minute and hour hands

  1. Choose Rectangle tool from Toolbox and create a rectangle in the design area. Don’t worry about size and placement at this point.
  2. Rename the [Rectangle] to “MinuteHand”.
  3. Make sure you have MinuteHand selected.
  4. In Properties.Brushes;
    • Set Fill to “PhoneForegroundBrush”.
    • Set Stroke to “No Brush”.
  5. In Layout section;
    • Set Width to 2 and Height to 20.
    • Set HorizontalAlignment to Center.
    • Set VerticalAlignment to Bottom.
    • Set Bottom margin to 25 and all others to 0.
  6. In Properties.Transform;
    • Select Center Point tab.
    • Set X to 0.5.
    • Set Y to 1.
  7. Copy and paste “MinuteHand” control and name it “HourHand”. Keep everything same and change only the Properties.Layout.Height to 13.

06_CreateMinuteHand

Step 9 : Create Storyboard for moving hands

  1. In Objects and Timeline, click on “+” sign to add a new storyboard.
  2. Name the storyboard as “MoveHands”.

07_CreateStoryBoard

Step 10 : Create animation for minute hand

  1. In timeline window slide the marker to 3 second.
  2. Select MinuteHand control.
  3. In Properties.Transform select Rotate tab and set Angle property to 1440.

07b_CreateStoryBoard

Step 11 : Create animation for hour hand

  1. Select HourHand control.
  2. In Properties.Transform select Rotate tab and set Angle property to 360.
  3. c. In timeline windows click on play button to see hands are rotating properly (Hour hand completes 1 rotation and minute hand completes 4 rotations in 3 seconds).

07c_CreateStoryBoard

Step 11B : Follow me on Twitter 😀

Step 12 : Review XAML code

Close Blend and go back to XAML view of UCWaitSpinner in VS. You should see following XAML code:

<UserControl x:Class="XAMLControls.UCWaitSpinner"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">
	<UserControl.Resources>
		<Storyboard x:Name="MoveHands">
			<DoubleAnimation Duration="0:0:3" To="360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="HourHand" d:IsOptimized="True"/>
			<DoubleAnimation Duration="0:0:3" To="1440" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="MinuteHand" d:IsOptimized="True"/>
		</Storyboard>
    </UserControl.Resources>

    <Viewbox x:Name="LayoutRoot">
    	<Grid Width="50" Height="50">
    		<Ellipse Margin="0">
    			<Ellipse.Stroke>
    				<SolidColorBrush Color="{StaticResource PhoneForegroundColor}"/>
    			</Ellipse.Stroke>
    		</Ellipse>
    		<Ellipse Margin="0" Width="4" Height="4" HorizontalAlignment="Center" VerticalAlignment="Center">
    			<Ellipse.Fill>
    				<SolidColorBrush Color="{StaticResource PhoneForegroundColor}"/>
    			</Ellipse.Fill>
    		</Ellipse>
    		<Rectangle x:Name="MinuteHand" Height="20" Margin="0,0,0,25" Width="2" StrokeThickness="0" HorizontalAlignment="Center" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,1">
    			<Rectangle.RenderTransform>
    				<CompositeTransform/>
    			</Rectangle.RenderTransform>
    			<Rectangle.Fill>
    				<SolidColorBrush Color="{StaticResource PhoneContrastBackgroundColor}"/>
    			</Rectangle.Fill>
    		</Rectangle>
    		<Rectangle x:Name="HourHand" Height="13" Margin="0,0,0,25" Width="2" StrokeThickness="0" HorizontalAlignment="Center" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,1">
    			<Rectangle.RenderTransform>
    				<CompositeTransform/>
    			</Rectangle.RenderTransform>
    			<Rectangle.Fill>
    				<SolidColorBrush Color="{StaticResource PhoneContrastBackgroundColor}"/>
    			</Rectangle.Fill>
    		</Rectangle>
    	</Grid>
    </Viewbox>
</UserControl>

Step 13 : Add appear disappear animations

Add AppearClock and DisappearClock animations just below MoveHands inside UserControl.Resource, like so:

        <Storyboard x:Name="AppearClock">
            <DoubleAnimation Duration="0:0:0.3" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True"/>
        </Storyboard>
        <Storyboard x:Name="DisappearClock">
            <DoubleAnimation Duration="0:0:2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="LayoutRoot" d:IsOptimized="True"/>
        </Storyboard>

Step 14 : Update code behind

Open code behind UCWaitSpinner.xaml.cs and add following lines to its constructor:

        public UCWaitSpinner()
        {
            InitializeComponent();
            MoveHands.RepeatBehavior = RepeatBehavior.Forever;
            LayoutRoot.Opacity = 0d;
            DisappearClock.Completed += (object sender, EventArgs e) => { MoveHands.Stop(); };
        }

Step 15 : Add start functionality

Add a public Start method to the class:

        public void Start()
        {
            MoveHands.Stop();
            AppearClock.Begin();
            MoveHands.Begin();
        }

Step 16 : Add stop functionality

Add a public Stop methods to the class:

        public void Stop()
        {
            DisappearClock.Begin();
        }

Step 17 : Build

Build XAMLControls project. If your project builds properly you should see UCWaitSpinner listed in your Toolbox in XAML Controls.

Step 18 : Add spinner to form

Open MainPage.xaml from the main project WaitSpinner and drag UCWaitSpinner from the Toolbox to the page. Open MainPage.xaml in code view and your will find the newly added control in ContentPanel:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
                <my:UCWaitSpinner/>
        </Grid>

Step 19 : Edit control properties

In MainPage.xaml name UCWaitSpinner control as “waitSpinner”, add Height and Width properties with a value of 120 in both, and wrap the control in a StackPanel:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <my:UCWaitSpinner x:Name="waitSpinner" Height="120" Width="120" />
            </StackPanel>
        </Grid>

Step 20 : Add buttons to control test

Add two buttons, just below WaitSpinner, Start and Stop with Click handlers to control WaitSpinner:

        <my:UCWaitSpinner x:Name="waitSpinner" Height="120" Width="120" />
        <Button x:Name="buttonStart" Content="Start" Click="buttonStart_Click"/>
        <Button x:Name="buttonStop" Content="Stop"  Click="buttonStop_Click"/>

Step 21 : Write code in click handlers

Open MainPage.xaml.cs and call Start and Stop of WaitSpinner in buttons’ click handlers:

        private void buttonStart_Click(object sender, RoutedEventArgs e)
        {
            waitSpinner.Start();
        }

        private void buttonStop_Click(object sender, RoutedEventArgs e)
        {
            waitSpinner.Stop();
        }

You can run your code and click on Start button to start spinner. Click on Stop button and spinner will slowly fade out.

Let’s see the example code to integrate the control with background processes.

Make following changes to MainPage.xaml’s ContentPanel control:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" x:Name="textBlockSeconds" Text="..."/>
                    <my:UCWaitSpinner Grid.Column="1" x:Name="waitSpinner2" Height="90" Width="90" />
                </Grid>
                <my:UCWaitSpinner x:Name="waitSpinner" Height="120" Width="120" />
                <Button x:Name="buttonStart" Content="Start" Click="buttonStart_Click"/>
                <Button x:Name="buttonStop" Content="Stop"  Click="buttonStop_Click"/>
                <Button x:Name="buttonBackground" Content="Background" Click="buttonBackground_Click"/>
            </StackPanel>
        </Grid>

And add following code to the code behind MainPage.xaml.cs:

    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        Thread bgThread;
        public MainPage()
        {
            InitializeComponent();
            bgThread = new Thread(new ThreadStart(() => 
            {
                Dispatcher.BeginInvoke(new Action(() => { waitSpinner2.Start(); }));
                for (int cnt = 0; cnt < 5; cnt++)
                {
                    Dispatcher.BeginInvoke(new Action(() => { textBlockSeconds.Text = string.Format("Step - {0}/4", cnt); }));
                    Thread.CurrentThread.Join(2000);
                }
                Dispatcher.BeginInvoke(new Action(() => { waitSpinner2.Stop(); }));
            }));
        }

        private void buttonStart_Click(object sender, RoutedEventArgs e)
        {
            waitSpinner.Start();
        }

        private void buttonStop_Click(object sender, RoutedEventArgs e)
        {
            waitSpinner.Stop();
        }

        private void buttonBackground_Click(object sender, RoutedEventArgs e)
        {
            buttonBackground.IsEnabled = false;
            bgThread.Start();
        }
    }

F5. You should see something like this:

Download entire code here.

C#|XAML : ListBox – Search, Filter, and Highlight (3/3)

Highlight colors. by pasukaru76, on Flickr
Highlight colors., a photo by pasukaru76 on Flickr.

In part 1  and part 2 we set up our ListBox and search TextBox in MainPage.XAML and filtered the list on-the-fly for the text entered in the text box. To see search/filter/highlight code in action in a published app, you can download my app for free.

After having filtered the list, in this post we will add code to highlight the searched text in each field of the items. The highlighted text will be in current accent color on the device, italicized, and underlined.

Let’s open MainPage.xaml.cs and add two new fields at MainPage class level:

        EventHandler _listBoxItemsRearrangedHandler;
        bool    _trapListBoxLayoutUpdate = true;

…and in the constructor initialize the handler:

            _listBoxItemsRearrangedHandler = new EventHandler(listBoxItems_Rearranged);

In the private method prepareFilteredList, we created in Part 2, set the _trapListBoxLayoutUpdate flag and also start listening to LayoutUpdated event of listBoxTextItems:

            _trapListBoxLayoutUpdate = true;
            listBoxTextItems.LayoutUpdated -= new EventHandler(_listBoxItemsRearrangedHandler);
            listBoxTextItems.LayoutUpdated += new EventHandler(_listBoxItemsRearrangedHandler);

Add following two methods for the core highlighting logic:

        void listBoxItems_Rearranged(object sender, EventArgs e)
        {
            if (_trapListBoxLayoutUpdate)
            {
                foreach (var ob in listBoxTextItems.Items)
                {
                    ListBoxItem lbi = listBoxTextItems.ItemContainerGenerator.ContainerFromItem(ob) as ListBoxItem;
                    if (lbi != null)
                    {
                        IEnumerable<TextBlock> _allTextBlocks = ViewHelpers.GetChildrenByType<TextBlock>(VisualTreeHelper.GetChild(lbi, 0));
                        foreach (TextBlock _txtBlock in _allTextBlocks)
                        {
                            if (
                                (
                                _txtBlock.Name == "templateTextBlockName" ||
                                _txtBlock.Name == "templateTextBlockNote" ||
                                _txtBlock.Name == "templateTextBlockAdd"
                                ) &&
                                _txtBlock.Text.ToUpper().Contains(textBoxSearch.Text.ToUpper())
                                )
                            {
                                HightlightText(_txtBlock, textBoxSearch.Text);
                            }
                        }
                    }
                }
                _trapListBoxLayoutUpdate = false;
            }
        }
        public static void HightlightText(TextBlock textBlockTarget, string highlightedText)
        {

            string Text = textBlockTarget.Text;
            textBlockTarget.Inlines.Clear();
            int _indexOfHighlightedTextInTarget = Text.ToUpper().IndexOf(highlightedText.ToUpper());
            Color highlightColor = (Color)Application.Current.Resources["PhoneAccentColor"];
            Run r = new Run();
            r.Text = Text.Substring(0, _indexOfHighlightedTextInTarget);
            textBlockTarget.Inlines.Add(r);


            r = new Run();
            r.Text = highlightedText;
            r.FontWeight = FontWeights.Bold;
            r.FontStyle = FontStyles.Italic;
            r.TextDecorations = TextDecorations.Underline;
            r.Foreground = new SolidColorBrush(highlightColor);
            textBlockTarget.Inlines.Add(r);

            r = new Run();
            r.Text = Text.Substring(_indexOfHighlightedTextInTarget + highlightedText.Length, Text.Length - (_indexOfHighlightedTextInTarget + highlightedText.Length));
            textBlockTarget.Inlines.Add(r);
        }

F5 and when the form is up, type Bill in the text box. You will notice as you are typing list is filtering and the text being typed in the text box is getting highlighted in different fields of the items in the ListBox.

highlight

A more extensive implementation can be found in this app.

Hope you find this code useful.

Happy searching/filtering/highlighting 😀

C#|XAML : ListBox – Search, Filter, and Highlight (2/3)

Filter by Joe Edwards, on Flickr
Filter, a photo by Joe Edwards on Flickr.

In part 1 we set up our ListBox and search TextBox in MainPage.XAML. We also created the ViewModel class which will be shown in the ListBox. You can download my app for free which has the complete working filter/search/highlight function.

In this post we will add functionality to filter our ListBox items on the basis of text entered in TextBox. We will filter the list on the fly without any query. To achieve this we will utilize filter event of CollectionViewSource. We will also create a field in Profile class to concatenate different properties which are going to participate in search.

Add new property to Profile class like so:

        public string SearchText { get { return string.Format("{0}|{1}|{2}", Name, Address, Note); } }

Update the code behind MainPage.xaml.cs to add a filter event handler. This is how the complete code of MainPage class will look like:

    public partial class MainPage : PhoneApplicationPage
    {
        ObservableCollection<Profile> _infoList = new ObservableCollection<Profile>();
        FilterEventHandler _searchFilter;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            _infoList.Add(new Profile("A Kejriwal", "New Delhi, India", "I am common man A"));
            _infoList.Add(new Profile("Bill Gates", "Microsoft One", "I am not a common man"));
            _infoList.Add(new Profile("Bill Burr", "Comedy Central", "Don't say there is no reason"));
            _infoList.Add(new Profile("Kartavya Sharma", "Street dhimka", "What do you mean?"));
            _infoList.Add(new Profile("Louis CK", "HBO One Night", "Bill curses a lot in comedy"));
            _infoList.Add(new Profile("Sanjay Sharma", "Street falana", "What do you mean?"));
            _infoList.Add(new Profile("Z Kejriwal", "New Delhi, India", "Don't underestimate the power"));

            _searchFilter = new FilterEventHandler(onSearchResultsFiltering);

            textListViewSource.Source = null;
            textListViewSource.Source = _infoList;
            textListViewSource.Filter += _searchFilter;
            listBoxTextItems.DataContext = _infoList;
        }

        private void onSearchResultsFiltering(object sender, FilterEventArgs e)
        {
            Profile _info = e.Item as Profile;
            if (_info != null)
            {
                if (_info.SearchText.ToUpper().Contains(String.Format("{0}", textBoxSearch.Text).ToUpper()))
                {
                    e.Accepted = true;
                }
                else
                {
                    e.Accepted = false;
                }
            }
        }
    }

Next, we want our TextBox to initiate filtration of the ListBox items as soon as text is changed by user. To achieve this behavior, we will trap KeyUp event of TextBox. Let’s update XAML to add the event handler.

<TextBox Grid.Row="0" x:Name="textBoxSearch" KeyUp="textBoxSearch_KeyUp"/>

As we have the event handler code inserted by VS in the code behind, let’s update it to refresh our ListBox with latest filtered list:

        private void textBoxSearch_KeyUp(object sender, KeyEventArgs e)
        {
            Dispatcher.BeginInvoke(new Action(prepareFilteredList));
        }
        private void prepareFilteredList()
        {
            textListViewSource.View.Refresh();
        }

We are ready! F5. Type ‘Bill’ in TextBox. You will see that the list gets filtered on the fly, while you type. Filtered list should look like this :
FilteredList

In the next part of the series, we will see how to highlight the searched text in the fields in ListBox.

To be continued…(Part 3)

C#|XAML : ListBox – Search, Filter, and Highlight (1/3)

C#|XAML : ListBox – Search, Filter, and Highlight (1/3)

In this 3 part series we will go through c#/XAML code to setup Listbox with multiple rows of information having ability to search, filter and highlight the text in searched items. To see the actual running code of this ListBox in live app, you can check my app. The topics of different parts in this series are as follows:

  • Part 1: Set-up form with TextBox and ListBox with example model class
  • Part 2: Add search and filter ability
  • Part 3: Highlight searched text

Setup Test XAML Form

This is our default MainPage.XAML. We will add a TextBox control and a ListBox control to this page. TextBox control is where we will input the text to be searched in the ListBox items. ListBox will show items. Each item has three information fields. These fields are: Name, Address, and Note. Let’s first update the XAML created by Studio.

Replace the default “ContentPanel” control with following Grid:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="80"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <TextBox Grid.Row="0" x:Name="textBoxSearch" KeyUp="textBoxSearch_KeyUp"/>
            <ListBox Grid.Row="1" x:Name="listBoxTextItems"></ListBox>
        </Grid>

Create ViewModel Class

The class which feeds data to the ListBox is Profile and contains three basic properties : Name, Address, and Note. For the sake of keeping this example simple, let’s write this class in the code-behind, MainPage.xaml.cs (please note, in real world, ViewModel classes do not go in the code-behinds and they usually have mechanism to broadcast change messages to UI. To keep the focus on the subject in hand, we are only writing just the essential code).

    public class Profile
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public string Note { get; set; }
        public Profile(string name, string add, string note)
        {
            Name = name;
            Address = add;
            Note = note;
        }
    }

Create List and connect View and ViewModel

Let’s first update MainPage.XAML to add CollectionViewSource to its resources and bind it to the ListBox. We need CollectionViewSource to filter our data in the view.

    <phone:PhoneApplicationPage.Resources>
        <CollectionViewSource x:Name="textListViewSource">
        </CollectionViewSource>
    </phone:PhoneApplicationPage.Resources>

Update the ListBox definition to add the CollectionViewSource:

            <ListBox Grid.Row="1" x:Name="listBoxTextItems" ItemsSource="{Binding Source={StaticResource textListViewSource}}">

We also want our ListBox to show these items in different sizes and colors so that three different rows in each item can be differentiated visually. So, we will add a visual template for ListItem and assign it to the ListBox.

The style definition will go in the Resources section:

        <Style x:Key="styleInfoTextListBox" TargetType="ListBoxItem">
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Grid x:Name="gridDataTemplate" Margin="15,5,5,5">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Row="0" x:Name="templateTextBlockName" Text="{Binding Name}" FontFamily="Segoe WP Black" FontSize="{StaticResource PhoneFontSizeExtraLarge}" Foreground="White"/>
                            <TextBlock Grid.Row="1" x:Name="templateTextBlockAdd" Text="{Binding Address}" FontFamily="Segoe WP" FontSize="{StaticResource PhoneFontSizeLarge}" Foreground="White" Opacity="0.8"/>
                            <TextBlock Grid.Row="2" x:Name="templateTextBlockNote" Text="{Binding Note}" FontFamily="Segoe WP Light" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="White" Opacity="0.8"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Update the ListBox definition one last time to apply the style on ListItems to add the CollectionViewSource:

<ListBox Grid.Row="1" x:Name="listBoxTextItems" ItemsSource="{Binding Source={StaticResource textListViewSource}}" ItemContainerStyle="{StaticResource styleInfoTextListBox}">

Our ListBox is ready to show the data. Now let’s switch back to MainPage.xaml.cs. We will create an ObservableCollection of Profile type and add some example data to it. We will write this code in MainPage.xaml.cs. Also in the constructor of our page we will set CollectionViewSource’s source and ListBox’s DataContext to connect our list with the data. Our MainPage.xaml.cs will look like this:

    public partial class MainPage : PhoneApplicationPage
    {
        ObservableCollection<Profile> _infoList = new ObservableCollection<Profile>();
        // Constructor
        public MainPage()
        {
            InitializeComponent();

            _infoList.Add(new Profile("A Kejriwal", "New Delhi, India", "I am common man A"));
            _infoList.Add(new Profile("Bill Gates", "One Microsoft, Redmond", "I am not a common man"));
            _infoList.Add(new Profile("Bill Burr", "Comedy Central", "Don't say there is no reason"));
            _infoList.Add(new Profile("Kartavya Sharma", "Street dhimka", "What do you mean?"));
            _infoList.Add(new Profile("Louis CK", "HBO One Night", "Bill curses a lot in comedy"));
            _infoList.Add(new Profile("Sanjay Sharma", "Street falana", "What do you mean?"));
            _infoList.Add(new Profile("Z Kejriwal", "New Delhi, India", "Don't underestimate the power"));

            textListViewSource.Source = _infoList;
            listBoxTextItems.DataContext = _infoList;
        }
    }

Let’s F5 our form. You should see this on your emulator:
List

In next post we will write code to respond to search query in TextBox and filter data in ListBox.

To be contd… Part 2

C#|.NET : Generic Concurrent Queue (6/6)

... by g corallo, on Flickr
, a photo by g corallo on Flickr.

Visit these posts for Part 1, Part 2, Part 3, Part 4, Part 5, and real life implementation

In this concluding post we will make some changes to further separate some concerns and see multiple queues in action. First we will take the queue initialization to higher level in availability and define the queues in our top level class, i.e. App.xaml.cs. This way our queues are available everywhere in the application. We will move out background enqueue-ing to class level and expose it through a  method. This is to encapsulate the behavior to self-enqueue-ing in the class itself. So the user of the class does not have to know anything about the queue, they could simply call the class’ method and the class will queue itself for background work. Let’s start.
First, let’s modify the code of TypeOneTask class we created in Part 5, and encapsulate enqueue behavior in the class itself. We will introduce a new public method QueueInForBackgroundWork:

        public void QueueInForBackgroundWork()
        {
            Debug.WriteLine("UI Thread : {0} enqueue starting", this.Name);
            App.t1Queue.Process(this, true, false);
            Debug.WriteLine("UI Thread : {0} enqueue finished", this.Name);
        }

Before going to consumption code for this method in our main page’s code behind, let’s first set-up TypeTwoTask class and a new queue for the same. We will create a new class file TaskTwoQueue.cs and write code in this file. Most of the code in these classes is similar to what we created in Part5, so I will write all the code in one code block:

namespace TaskQueue
{
    public class TaskTwoQueue : ConcurrentQueue<TypeTwoTask>
    {
        #region queue implementationsc
        TypeTwoTaskEqualityComparer _itemEqualityComparer = new TypeTwoTaskEqualityComparer();
        public override bool IsQueueAlive
        {
            get
            {
                return base.IsQueueAlive;
            }
        }
        public override IEqualityComparer<TypeTwoTask> QueueItemEualityComparer
        {
            get
            {
                return _itemEqualityComparer;
            }
        }
        public override bool IsQueueAvailableForEnqueue()
        {
            if (this.Count > 10)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        protected override void ProcessRequest(TypeTwoTask taskRequest, bool Async)
        {
            taskRequest.Process();
        }
        public override void Exit(bool discardPendingRequests)
        {
            base.Exit(discardPendingRequests);
        }
        public override void DoWhenQueueGetsEmpty()
        {
            //doing nothing
        }
        #endregion
    }

    public class TypeTwoTask
    {
        Random testWait = new Random();
        public string Name { get; set; }
        public event EventHandler BackgroundProcessFinished;
        public TypeTwoTask(string name)
        {
            Name = name;
        }
        public void Process()
        {
            DateTime _st = DateTime.Now;
            Debug.WriteLine("BG Thread : Task {0} starting @ {1}", Name, _st.ToString("hh:mm:ss.fff"));
            Thread.CurrentThread.Join(testWait.Next(735, 1923));
            Debug.WriteLine("BG Thread : Task {0} Ended @ {1}", Name, DateTime.Now.ToString("hh:mm:ss.fff"));
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (BackgroundProcessFinished != null)
                {
                    BackgroundProcessFinished(this, new EventArgs());
                }
            });
        }
        public void QueueInForBackgroundWork()
        {
            Debug.WriteLine("UI Thread : {0} enqueue starting", this.Name);
            App.t2Queue.Process(this, true, false);
            Debug.WriteLine("UI Thread : {0} enqueue finished", this.Name);
        }
    }

    public class TypeTwoTaskEqualityComparer : IEqualityComparer<TypeTwoTask>
    {
        public bool Equals(TypeTwoTask A, TypeTwoTask B)
        {
            if (A != null && B != null)
            {
                return A.Name == B.Name;
            }
            else
            {
                return false;
            }
        }
        public int GetHashCode(TypeTwoTask itm)
        {
            return itm.GetHashCode();
        }
    }

}

We are ready with our second queue. We will introduce this queue in our application at the application level. In app.xaml.cs we will define both the queues like so (mind that both the queues are static):

    public partial class App : Application
    {
        public static TaskOneQueue t1Queue = new TaskOneQueue();
        public static TaskTwoQueue t2Queue = new TaskTwoQueue();
    }

The final user of our two classes, the main page, now, does not need to know about the queue (for previous code see part 5). It will only define the fields of appropriate task type, and call its QueuInForBackgroundWork as and when required. To demonstrate this behavior, we will modify MainPage.xaml.cs. We will first define 3 tasks of both the types at the page level. We will then have event handlers for both the types of the tasks to have informed about the completion of the task on UI thread. Button_click enqueues TypeOneTask in the queue by calling QueueInForBackgroundWork method and buttonDummy1_Click does the same for TypeTwoTask. Here is the code:

    public partial class MainPage : PhoneApplicationPage
    {
        TypeOneTask _t1 = new TypeOneTask("Type1 Task-1");
        TypeOneTask _t2 = new TypeOneTask("Type1 Task-2");
        TypeOneTask _t3 = new TypeOneTask("Type1 Task-3");

        TypeTwoTask _t4 = new TypeTwoTask("Type2 Task-4");
        TypeTwoTask _t5 = new TypeTwoTask("Type2 Task-5");
        TypeTwoTask _t6 = new TypeTwoTask("Type2 Task-6");

        public MainPage()
        {
            InitializeComponent();
            this.BackKeyPress += new EventHandler<System.ComponentModel.CancelEventArgs>(MainPage_BackKeyPress);
            _t2.BackgroundProcessFinished += (object sender, EventArgs e) => { Debug.WriteLine("UI Thread : TypeOneTask _t1 finished!"); };
            _t3.BackgroundProcessFinished += (object sender, EventArgs e) => { Debug.WriteLine("UI Thread : TypeOneTask _t2 finished!"); };
            _t5.BackgroundProcessFinished += (object sender, EventArgs e) => { Debug.WriteLine("UI Thread : TypeTwoTask _t5 finished!"); };
            _t6.BackgroundProcessFinished += (object sender, EventArgs e) => { Debug.WriteLine("UI Thread : TypeTwoTask _t6 finished!"); };
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _t1.QueueInForBackgroundWork();
            _t2.QueueInForBackgroundWork();
            _t3.QueueInForBackgroundWork();
        }
        private void buttonDummy1_Click(object sender, RoutedEventArgs e)
        {
            _t4.QueueInForBackgroundWork();
            _t5.QueueInForBackgroundWork();
            _t6.QueueInForBackgroundWork();
        }

        private void buttonDummy2_Click(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine("UI Thread : Dummy button 2 clicked!");
        }

    }

When you run the the app in debug mode, you get three buttons – Button1, dummy 1, and dummy 2, same as we had in part 5. This time Button1 and dummy 1 both enqueue tasks and dummy 2 is just to demonstrate that UI thread is free. Now, with 1-2 seconds delay, click on these three buttons top to bottom. You will get following log in your Debug output:

Output.Debug

UI Thread : Type1 Task-1 enqueue starting
UI Thread : Type1 Task-1 enqueue finished
UI Thread : Type1 Task-2 enqueue starting
UI Thread : Type1 Task-2 enqueue finished
UI Thread : Type1 Task-3 enqueue starting
UI Thread : Type1 Task-3 enqueue finished
BG Thread : Task Type1 Task-1 starting @ 12:29:35.530
UI Thread : Type2 Task-4 enqueue starting
UI Thread : Type2 Task-4 enqueue finished
BG Thread : Task Type2 Task-4 starting @ 12:29:36.502
UI Thread : Type2 Task-5 enqueue starting
UI Thread : Type2 Task-5 enqueue finished
UI Thread : Type2 Task-6 enqueue starting
UI Thread : Type2 Task-6 enqueue finished
BG Thread : Task Type1 Task-1 Ended @ 12:29:37.403
BG Thread : Task Type1 Task-2 starting @ 12:29:37.413
BG Thread : Task Type2 Task-4 Ended @ 12:29:37.575
BG Thread : Task Type2 Task-5 starting @ 12:29:37.581
UI Thread : Dummy button 2 clicked!
BG Thread : Task Type1 Task-2 Ended @ 12:29:38.500
BG Thread : Task Type1 Task-3 starting @ 12:29:38.506
UI Thread : TypeOneTask _t1 finished!
BG Thread : Task Type2 Task-5 Ended @ 12:29:38.635
BG Thread : Task Type2 Task-6 starting @ 12:29:38.642
UI Thread : TypeTwoTask _t5 finished!
BG Thread : Task Type1 Task-3 Ended @ 12:29:39.576
UI Thread : TypeOneTask _t2 finished!
BG Thread : Task Type2 Task-6 Ended @ 12:29:39.691
UI Thread : TypeTwoTask _t6 finished!

The analysis of this output shows that Type1 tasks were enqueued first, because I clicked Button1 first, and as soon as all three tasks are enqueued UI thread was freed. Also, “Task Type1 Task-1” started its BG work. Because UI was free, after two seconds, I clicked Dummy 1 button which enqueued all the three tasks of TypeTwoTask in its queue. Both these queues are working on their own background threads. UI thread is completely free. When tasks get over UI gets a message.

To summarize, Generic Concurrent Queue has following characteristics:

  • Generic and abstract, to be inherited to implement for any type.
  • Process requests can be queued up for BG thread.
  • Has a single lazy-init BG thread.
  • Supports sync and async requests.
  • By supplying a sync process request, you can stop other processes in queue and have sync request process first. Queue resumes automatically after the sync task is over.
  • Queue can be paused and restarted as and when required.
  • Queue can be exited | killed as and when required.
  • Inherited class defines rules for Queue capacity.
  • Inherited class defines rules for process request duplicate value.
  • Uses basic lock/wait/pulse mechanism, so compatible with almost all variants of .NET

Please feel free to comment. Hope you find this concurrent queue useful.

NokiaX Strategy : WPDev Fears!

I thought Normandy etc were rumors and Nokia+MS will never make the mistake of trying to cross enemy lines (yes, i know there are no enemy lines for businesses. but…) to win some battles on a tough to fight ground. I say Nokia+MS because I am not for believing that at this juncture of the deal Nokia could have gone and built Android devices on its own when it could not do it back then when they were an independent company. Tough fight because, Android scene is totally dominated by a much larger player than Nokia in hardware and much larger player than Microsoft in mobile OS. But, they did it. And, boy, if this is a strategy (as our Daniel Rubino of WPCentral suggests in his post here – Nokia’s shrewd move with the Nokia X undermines Google, bolsters Microsoft), are they really thinking! Are they thinking about those phone buyers who want a simpler Nokia path to stay on? Are they thinking about the confusion they have created for new buyers? Are they thinking about the dent they have made to the psyche of early adopters and loyal Windows Phone users, who did not come to Windows Phone because they couldn’t leave without, but they came to it because they could not stand other platforms? Are they thinking about the developers who helped built an ecosystem of healthy numbers of apps around a new, fresh, and promising platform, i.e. WP? Are they thinking that Windows Phone developers need to reap from their hard efforts they have put into WP? Are they thinking that this move is like shooing away developers from WP development? What are they thinking about? With NokiaX they have confused consumers. With NokiaX they have confused developers.

Just for the sake of argument, have a look at the impact of this strategy, if it is one, on phone buyers’ decision making. Decide for yourself, if this is a helping strategy or confusing strategy.

NokiaXStragegyConfusing

New Buyer’s confusion: Should I buy Nokia Asha or NokiaX?
Nokia Asha Users’ confusion: Now, should I buy NokiaX+ or Lumia 520?
NokiaX users’ confusion: Should I buy NokiaX+ or Lumia 520?
NokiaX+ users’ confusion: Should I buy Lumia or NokiaXL or some other high end Android?

WPDev’s confusion: Should I continue investing in WP ecosystem?

I am hoping Microsoft will soon do something to elevate WPDevs’ confidence in one of the best smartphone platforms, Windows Phone. WPDevs are your own devs, Microsoft. We know you are device and services company now but do not leave the technology and its developers in a fix. Let us know. We are also doing business. Hoping for the best!

Where Are The Buyers of Your App?

Fairly popular timekeeping app Avirall is on Windows Phone Store for about 5.5+ months now and has been downloaded 200,000+ times with 12,000+ reviews and 4.5+ stars average ratings. Download data of Avirall could be a good set of data to know about users’ buying behavior on Windows Phone store. With the help of latest information available in Excel export from Windows Phone Dev Center, I created following graph. The comparison between free, trial, and paid downloads can give a good deal of insight into users’ app download and buying behaviors in different countries. I gather following from the chart:

  • USA is clear leader in both free and paid downloads.
  • US buyers care less about trying before buying.
  • But, Germans care even less, and they are good buyers as well.
  • Indians want it free, also try it (more than even USA) but buy very little.
  • Chinese try more than they download for free, and buy more than Indians but less than English.
  • Your app’s buyers may be in USA, Germany, UK, China, Russia, Australia, France, and HK SAR.
  • [What do you gather?]

PaidTrialFree