Making a quick rating user control for Windows Phone 8.1

First Words

Usually when someone is working on Windows Phone 8.1 and usually if he’s the guy who just came from Windows Phone 8 development, the first thing he misses is all the toolkits lying around like the Windows Phone Toolkit or Coding4Fun Toolkits. Thus, missing a rating control is not new. So, let’s get our hands dirty and make a little 5 starred rating control fast enough to solve our problem at least to a minimum extent.

Design First!

Okay, to do this thing fast, we might need to make at least a little bit of groundwork in design, I’m going to use Microsoft Expression Design for it. You guys can get the free version from here. It’s pretty lightweight and we can practically export stuff straight to Blend for Visual Studio!

So, let’s go over Microsoft Expression Blend and create a new document. Take a size to your preference as you need it. Let’s draw some stars! To get started, look on the left toolbar and select Polygons.

1

After you select polygons, drag your mouse pointer in the artboard to draw anything that pops off. Now, it might be any kind of polygon, starting from a triangle, like the following came up with too much of points.

2

To rectify this, we need to make sure it has 5 points and an inner depth above 40% and close to 50% so it looks like a star, you can modify the existing one you made or set the proper settings and make a new one. To do that, look on the right on Edit Polygon dialog and change the points to 5 and move the innder depth to 47%. If you want to create a new one you will see the dialog name is Create Polygon. You can go for anything in between 45% tp 50%, I used 47% in this case.

3 4

 

 

Now, with the proper settings set with the polygon give it a yellowish shade and no borders please. And copy the stars and set them side by side so you can have 5 stars in a line that resembles a regular rating control. So, in the artboard it might look pretty close to the one following:

5

Now, what we want to do is put these together on a gradient so it resembles more to the rating control. But before we go do that, we need to make the stars act as a compound path together. So, lets go ahead and select all of them and select Object -> Compound Path -> Make so all the stars can work as a compound path.

6

Now, it’s time to put a gradient over it. Select a yellow to white gradient and put it on your rating control from left to right. Now, there comes a trick, at first you will see the color melted down in the middle, in a rating control we need a clear difference of color to make sure that it looks like one.

7

Now, click on the gradient bar in the middle to put a gradient stop in there.

8

Now, drag the midpoints (the dots over the gradient bar) and put them together to make the color difference more prominent.

9

Now, if we move the Gradient Stop now, we will see the color changes are more prominent and the starts look a lot like rating control now.

10

Now let’s go over Visual Studio and create a Windows Phone 8.1 Project. Let’s put a Right Click on the solution name and add a user control.

11

12

Now, lets select the user control and open it on blend. Let’s select all the stars, copy it and just paste it on the grid of the user control. To your surprise, this thing will just get copied to blend just fine. And let’s make the height of the user control to 40 and the width to 200 just to get the user control to appropriate proportion. I copied a set of stars and put the background to a very light gray color and put it behind the ones we copied at first so it looks a bit more prominent even in a white background.

13

Now, the xaml for the usercontrol will look somewhat like the following:

<UserControl
    x:Class="RatingControlTest.usercontrol"
    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"
 
    d:DesignHeight="40"
    d:DesignWidth="200">

    <Grid>
        <Path Stretch="Fill"
              Data="M -1346.6,-259.247L -1358.76,-305.451L -1321.61,-335.489L -1369.31,-338.197L -1386.39,-382.816L -1403.71,-338.285L -1451.43,-335.823L -1414.43,-305.594L -1426.83,-259.454L -1386.65,-285.302L -1346.6,-259.247 Z M -1067.9,-259.247L -1080.07,-305.451L -1042.91,-335.489L -1090.61,-338.197L -1107.7,-382.816L -1125.01,-338.285L -1172.73,-335.823L -1135.73,-305.594L -1148.13,-259.453L -1107.95,-285.301L -1067.9,-259.247 Z M -1207.25,-259.247L -1219.41,-305.451L -1182.26,-335.489L -1229.96,-338.197L -1247.05,-382.816L -1264.36,-338.285L -1312.08,-335.823L -1275.08,-305.594L -1287.48,-259.453L -1247.3,-285.301L -1207.25,-259.247 Z M -928.552,-259.247L -940.718,-305.451L -903.562,-335.489L -951.264,-338.197L -968.35,-382.816L -985.666,-338.285L -1033.38,-335.823L -996.382,-305.594L -1008.79,-259.453L -968.602,-285.301L -928.552,-259.247 Z M -789.204,-259.247L -801.369,-305.451L -764.214,-335.489L -811.916,-338.197L -829.002,-382.816L -846.318,-338.285L -894.034,-335.823L -857.033,-305.594L -869.437,-259.453L -829.254,-285.301L -789.204,-259.247 Z "  
              UseLayoutRounding="False"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Height="Auto" Width="Auto" Fill="#FFDEDEDE"/>
        <Path Stretch="Fill"
              Data="M -1346.6,-259.247L -1358.76,-305.451L -1321.61,-335.489L -1369.31,-338.197L -1386.39,-382.816L -1403.71,-338.285L -1451.43,-335.823L -1414.43,-305.594L -1426.83,-259.454L -1386.65,-285.302L -1346.6,-259.247 Z M -1067.9,-259.247L -1080.07,-305.451L -1042.91,-335.489L -1090.61,-338.197L -1107.7,-382.816L -1125.01,-338.285L -1172.73,-335.823L -1135.73,-305.594L -1148.13,-259.453L -1107.95,-285.301L -1067.9,-259.247 Z M -1207.25,-259.247L -1219.41,-305.451L -1182.26,-335.489L -1229.96,-338.197L -1247.05,-382.816L -1264.36,-338.285L -1312.08,-335.823L -1275.08,-305.594L -1287.48,-259.453L -1247.3,-285.301L -1207.25,-259.247 Z M -928.552,-259.247L -940.718,-305.451L -903.562,-335.489L -951.264,-338.197L -968.35,-382.816L -985.666,-338.285L -1033.38,-335.823L -996.382,-305.594L -1008.79,-259.453L -968.602,-285.301L -928.552,-259.247 Z M -789.204,-259.247L -801.369,-305.451L -764.214,-335.489L -811.916,-338.197L -829.002,-382.816L -846.318,-338.285L -894.034,-335.823L -857.033,-305.594L -869.437,-259.453L -829.254,-285.301L -789.204,-259.247 Z "  
              UseLayoutRounding="False"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Height="Auto" Width="Auto">
            <Path.Fill>
                <LinearGradientBrush StartPoint="3.55262e-007,0.500002" EndPoint="1,0.500001">
                    <GradientStop Color="#FFFFCC00" Offset="0.6"/>
                    <GradientStop Color="#06FCFCFC" Offset="0.6"/>
                </LinearGradientBrush>
            </Path.Fill>
        </Path>

    </Grid>
</UserControl>

Code Comes Along

Now if we remember stuff clearly, when we moved the gradient stop in blend it looked like the rating bar value is changing. We just need to emulate that in code, that’s it. So, all we need to is change the Offset of <GradientStop> ‘s in LinearGradientBrush entry inside <Path.Fill>. So, we have to databind the offset from backend so we can access it from the usercontrol. And please remember this have to be 0.0 to 1 of course as thats the range for the offset value.

I renamed my user control to RatingControl and let’s move back to the code backend of RatingControl.xaml

public partial class RatingControl : UserControl
    {
        public RatingControl()
        {
            this.InitializeComponent();
        }

        DependencyProperty RateValueProperty = DependencyProperty.Register("RateValue", typeof(double), typeof(RatingControl), new PropertyMetadata(0.1, UpdateValue));

        private static void UpdateValue(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RatingControl control = d as RatingControl;
            control.Value = (double)e.NewValue;
        }

        private double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        private static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(RatingControl), new PropertyMetadata(0.1));

        public double RateValue
        {
            get
            {
                return (double)GetValue(RateValueProperty);
            }
            set
            {
                SetValue(RateValueProperty, value);
            }
        }

    }

Now, our job was to hook up the Value provided from backend. Now I used two DependencyProperty here instead of one because we are going to attach the value in the xaml using a element binding. The first DependencyProperty RateValueProperty has a PropertyMetadata of 0.1 and a function is attached to update the value in the xaml control (update the offset from the xaml).

And Value is the actual DependencyProperty Attached to the control and as it’s private it’s accessible only from inside. So we are exposing it using the RateValueProperty and update it with the Value Dependency Property. You can only use Value and expose it if you want.

Now all we have to do is hook it up in the xaml:

Let’s add a name to the Rating Control. Lets just add x:Name=”UserControl” in the UserControl Tag. And let’s tag the GradientStop property Offset on the ElementName “UserControl”. So, let’s modify the GradientStop tags as following:

<Path.Fill>
     <LinearGradientBrush StartPoint="3.55262e-007,0.500002" EndPoint="1,0.500001">
          <GradientStop Color="#FFFFCC00" Offset="{Binding Value, ElementName=UserControl}"/>
          <GradientStop Color="#06FCFCFC" Offset="{Binding Value, ElementName=UserControl}"/>
      </LinearGradientBrush>
</Path.Fill>

And voila! We are done!

Using the control

Using the control is pretty easy, add xmlns:local=”using:RatingControlTest” in the page tag and use it just like the following:

<Page
    x:Class="RatingControlTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:RatingControlTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <local:RatingControl Width="200" Height="40" RateValue="0.5"></local:RatingControl>
    </Grid>
</Page>

And it will look like the following:

14

Demo Project:

The demo project is here so you can test it yourself. Hope this helps! 😉

Using SQLite as local database with Universal Apps

The First Words

Usually when we are moving our existing Windows Phone 8 / Windows Phone Silverlight projects to Universal Apps, in most of the cases the common question that rises up is what should we use as a local database on it. And SQLite does a perfect job serving the universal apps a perfect local database. So, please keep your eyes posted here if you want to use the same database for both your projects in your universal app. So, why not get started?

Universal Apps

Univeresal Apps are the newest App Models designed for Windows Store to serve Apps in Windows Store and Windows Phone Store from a same project with shared codes as per your liking. To the ones who doesn’t know what an Uinversal App is, kindly visit this link so you can get a full idea how it works. To the ones who already know this, please continue.

SQLite With Universal App

To get SQLite going with your universal app, the first thing we should do is get SQLite for both Windows Phone 8.1 and Windows Runtime 8.1as Universal App points to both of the apps.

To install SQLite for Windows Store please visit:

http://visualstudiogallery.msdn.microsoft.com/1d04f82f-2fe9-4727-a2f9-a2db127ddc9a/view/

And you will stumble upon a screen like the following:
1

So, definitely the next thing to do is download this one, as soon as the VSIX installer is downloaded, install it. As, now we have SQLite for Windows Store here, let’s move so we can have SQLite for Windows Phone.

To install SQLite for Windows Phone 8.1 please visit:

http://visualstudiogallery.msdn.microsoft.com/5d97faf6-39e3-4048-a0bc-adde2af75d1b

This will lead to a similiar page, download the VSIX installer and install it too. The next thing we should check for whether we have installed what we need in our Visual Studio. I’m using a Visual Studio 2013 Ultimate version here and let’s go over Tools -> Extensions and Updates and go to the “SDK” section after under “Installed”. You will stumble upon SQLite for Windows Runtime and SQLite for Windows Phone 8.1 is listed as installed in your pc.

2

As now we are pretty sure that we have SQLite for Windows Phone 8.1 and Windows Store Apps, let’s create a new Universal App Project in Visual Studio.

SQLite With Universal App

Creating Univresal Apps are pretty same like other projects in Visual Studio. Just go over File->New Project and under Store Apps, let’s create a blank Universal App named UniversalSQLite.

3

In the Solution Explorer, you will see your projects divided into Windows Store, Windows Phone and Shared. Our job now is to reference SQLite into both Windows Store and Windows Phone projects so both of the projects has access to SQLite. In Windows 8.1 Solution, go over your references and add reference to the newly added SQLite libraries under extensions.

4

And do the same with Windows Phone 8.1 solution too. Go over references and add reference to the newly installed SQLite for Windows Phone 8.1 Libraries.

5
You will see some yellow excalamtion signs over the newly referenced libraries and the best thing to do right now is to build this. The first problem you are bound to see when you build is this:

6

Actually the problem says the solution itself. As these native libraries are extremely machine dependent the best thing to do here would be just go over configuration manager and set x86 as Platform for both projects.

7 8

Trying out x64 ended up XAML designer not rendering UI. So x86 is the safe choice. Don’t worry,  this will not prevent you to create the different platform version to be deployed on the store.

When you are ready just use the “Create App Packages” command. The best way to get that would be right clicking on the solution name and move over to store menu. But that’s later.

9

Get sqlite-net from Nuget

Well, if you put a build now, you will see everything has smoothed out. Now, what’d left is using SQLite. The first thing we need is a nuget package to cover all the internal intricacies we have on SQLite, thus comes in help sqlite-net  . This little nuget package is extremely handy and all you need to do to use this is to go over references and manage nuget packages. Search for sqlite-net and add it when the search results pop up.

10

This has to be done for both the Windows 8.1 and Windows Phone 8.1 projects of course as we intend to use this for both of them. You will see two classes named SQLite.cs and SQLiteAsync.cs is created into both of the projects. Just to remove duplicacies we can move them to shared project under a folder if you like.

11

Let’s get our hands dirty

So, lets get busy with some code, shall we?

Creating/Opening A Database:

To create/open a database all you have to do is someting like the following. This will actually create a database if it’s non existing or open connection to one if it’s existing.

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);

So, before doing that you might want to check whether the database exists or not.

public async Task&amp;lt;bool&amp;gt; DoesDbExist(string DatabaseName)
{
      bool dbexist = true;
      try
      {
         StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync(DatabaseName);

      }
      catch
      {
         dbexist = false;
      }

      return dbexist;
}

The reason we are looking at ApplicationData.Current.LocalFolder is sqlite-net creates database by default in that place.

Creating/Opening A Database:

Before creating a table you need to have a model to define a row on that specific table. The model might look like the following:

using SQLite;


namespace UniversalSqlLite.Model
{
    [Table(&quot;Students&quot;)]
    public class Student
    {
        [PrimaryKey, AutoIncrement]
        public int id { get; set; }

        public string Name { get; set; }

        public string EnrolledCourse { get; set; }

    }
}

Now you can just go ahead an create a Table as per your wish.

public async void CreateDatabase()
{
   SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
   await connection.CreateTableAsync&amp;lt;Student&amp;gt;();
}

CreateTableAsync will create the table if it’s not there. And it will update the table description if the Model is changed in any way than the previous one. As far now, it only supports column addition. It will not destroy any existing SQLite Table. So, you don’t have to worry about redoing this with an existing table.

If you look closely, you can see that you can adore the classes and the properties in the model with attributes defined in sqllite-net library. It’s almost the same you might see in Entitiy Framework.

The full list is to be found here:

Class attribute:

  • [Table(Name)]

Property attributes:

  • [AutoIncrement]
  • [PrimaryKey]
  • [Column(Name)]
  • [Indexed] | [Indexed(string name, int order)]
  • [Unique]
  • [Ignore]
  • [MaxLength(int length)]
  • [Collation(string name)]
  • [NotNull]

Dropping a Table:

Dropping table is a piece of cake too:

public async void DropDatabase()
{
    SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
    await connection.DropTableAsync&amp;lt;Student&amp;gt;();
}

Adding Records in the Table:

Inserting into SQLite is easy as the following:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var Student=new Student()
{
   Name=&quot;Swagata Prateek&quot;,
   EnrolledCourse=&quot;CSE 4203&quot;
};
await connection.InsertAsync(Student);

And if you feel like inserting a lot of stuff at a time why not using a list?

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);

var StudentList = new List&amp;lt;Student&amp;gt;()
{
    new Student()
    {
        Name=&quot;Swagata Prateek&quot;,
        EnrolledCourse=&quot;CSE 4203&quot;
        },
        new Student()
        {
            Name=&quot;Abidur Rahman&quot;,
            EnrolledCourse=&quot;CSE 4203&quot;
        },
        new Student()
        {
            Name=&quot;Ashiqur Rahman&quot;,
            EnrolledCourse=&quot;CSE 4203&quot;
        }
    };
            
await connection.InsertAllAsync(StudentList);

Pursue a Query

You can go for a Query in SQLite in quiet a number of ways. Let’s check out if we want to do it using LINQ, how would it be:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var queryVar=await connection.Table&amp;lt;Student&amp;gt;().Where(x=&amp;gt;x.Name.StartsWith(&quot;Swagata&quot;));

var queryResult = await queryVar.ToListAsync();
foreach (var item in queryResult)
{
    //Do your stuff
}

You can even do a manual SQL query if you feel like that:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var result = await connection.QueryAsync&amp;lt;Student&amp;gt;(&quot;Select Name FROM Students WHERE EnrolledCourse = ?&quot;, new object[] { &quot;CSE 4203&quot;});
foreach (var item in result)
{
    //Do your stuff
}

Update and Delete a Record

Any record can be updated as soon as it’s retrieved and updated back into the table.

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var Student=await connection.Table&amp;lt;Student&amp;gt;().Where(x=&amp;gt;x.Name.StartsWith(&quot;Swagata&quot;)).FirstOrDefaultAsync();

if(Student != null)
{
    Student.EnrolledCourse = &quot;CSE 4503&quot;;
    await connection.UpdateAsync(Student);
}

If you want to delete the same record all you have to do is:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var Student=await connection.Table&amp;lt;Student&amp;gt;().Where(x=&amp;gt;x.Name.StartsWith(&quot;Swagata&quot;)).FirstOrDefaultAsync();

if(Student != null)
{
    await connection.DeleteAsync(Student);
}

Summing up

We are going to take a little deep dive on the queries and make a sample app out of it in the next post. Meanwhile you can even go through Nicolò Carandini’s blog on SQLite with Universal app on the following links.

  1. Universal App With Sqlite Part -1
  2. Universal App With Sqlite Part -2

Hope you guys had fun!

Bus Map Dhaka – What can be next and how it can be done

Usually I talk about pretty current stuffs, let’s talk future now. And the future is needed to be talked now. Because after some days in this young app industry simple rss readers won’t be considered a quality app anymore. If you look around, Windows Phone in Bangladesh has walked a pretty silent but significant path. And I’m quiet happy that I walked a little too.

I hope the one who is reading this do know Bus Map Dhaka for Windows Phone. If you dont know, the following is the link: http://www.windowsphone.com/en-bd/store/app/bus-map-dhaka/3795f088-028a-4958-bea6-a2d0eb243bd

Now, let’s start talking how this was made. When I started doing this, the first thing that came into my mind is the actual scenario of Dhaka, if you really expect a local bus to come in the very right time exactly every day,  I guess you have optimism as your profession. So, along with finding the best route and other basic operations, I had to believe someday I would face the challenge which will “actually” solve the problem.

Traffic jams are usually one of the common phenomena here, very common as in like brushing your teeth everyday. If it’s not there, you get surprised. But it’s not the only thing that can keep you getting on the right bus. There’s bad road situations, there’s bus shortage, possibly anything that you can’t predict or manage.

I thought big big plans, like putting devices on buses and tracking down each one of them. But think once, just once. When nobody is even curious about putting proper fitness checks on a bus, maintaining  a device would be a overkill for them, and of course will lead my dream service to perish.

What I had it mind was a pretty simple one. If you ever heard of Ant Colony Optimization, I believe in case of Dhaka, it would come to a greater use . Because the shortest path is not always the “right path”.

If you want to know about ant colony optimization algorithm do a wiki read here:
http://en.wikipedia.org/wiki/Ant_colony_optimization_algorithms#Ant_Colony_System

I wanted to follow the traditional Ant Colony Optimization trait here. Let’s put a small city like Dhaka with us like below:

1

Pretty simple for Dhaka, eh? 😀 Let’s keep it simple for understanding. You will see Node D is kind of the hub of the city, much like our motijheel, mohakhali or other big bus junctions, right? Now, in this city there can be a number of buses, right? Essentially a Bus Route is nothing but a number of these nodes ordered by bus stops.

Let’s make some bus routes, shall we?
1. A-C-E

2. C-D-E-B-A

3. D-E-C-A

For simplicity lets assume all these bus goes and comes back in the same order. Now, I know what you guys are thinking, if I put “distance metrics” on these paths, it’s easy to find a suitable bus route. Like, if you want to take A trip from A to D you can chose bus number 2 or 3. Question is which one should you pick? What if there is more traffic jam in B-E junction and less in C-E? These data changes over time, even in fraction of ten minutes.  You can’t possibly decide every time.

Here ant colony comes so handy. The very basics of Ant Colony Optimization is based on how ants find best paths. In the natural world, ants  wander randomly and after finding food return to their colony while they continuously lay down pheromone trails. If other ants find such a path, they are likely not to keep traveling at random, but to instead follow the trail, returning and reinforcing it if they eventually find food. So, the fact is who knows the best path right now, the bus that just has gone to that path a few minutes ago. Just like the ant. The only deficit we have here is pheromone trail left by ants. Now, remember what we have in hand. We cant put too much on a local bus as they wont take care of it properly.

But what about known bus counters? If we manage to find only time-stamps of a bus arriving at a bus-stoppage somehow, we don’t need to know which one came, just spotting one on a counter, much like spotting an ant on a node.   And based on the frequency of that timestamp, you can actually verify the frequency of buses coming down there. If the adjacent roads are not doing well with traffic jams, you are bound to have a lesser frequency and if it’s smooth sailing you will have a solid frequency. Even if that sounds awkward we can even track ticket sales, although that would be far off, still a usable heuristic metric to understand whether people are actually getting up on a bus or not.

Now, based on that. We want to go to D from A.

We have two bus routes, 2 and 3. Now which to pick? All we have to do is check the pheromone/our very own heuristic cost metric trails and the route that currently has a more favorable reinforcement/feedback. No matter what comes in the road, traffic jams or stuff, within minutes, these would be updated. And as the buses are continuously traveling, the metric will always be updated. And further more, you can even predict a possible next bus time from this too. Or predict a best possible route to go from one place to another on a car. I know, for Dhaka, it might be a bit long shot, still…worth a try.

So, if you believe every bus is a ant running on a direction (although these are defined rather than random). Actually that makes us one step closer to goal. Because logically ant colony optimization finds a best path. As our possible paths are already defined, we don’t have to go through the first state.

There should be usually two steps of ant colony optimization:
1. Edge selection
2. Pheromone Update

As our paths are already defined, edge selection is basically finding eligible bus routes to go from one place to another, it could be a multiple bus journey but I will write about that later.

procedure BMD_Heuristic
    while(not_termination)
       TraverseRoutes()
       RouteActions()
       UpdateMetrics()
    end while
  end procedure

Let me know what you guys think of it and how can you help NerdCats take it to the next level. See ya!

Windows Phone micro UI hacks – simple drop shadows

Well, I was pretty upset when they took off effects support from silverlight, I really was. It was something I really loved thus I could’ve added a little bit of depth in design. I get the idea that it might help improving performance of UI rendering in a device.

So, I was trying out some little hacks, or you might say some faulty impersonations of making a drop shadow, so far I’m not close to that “quality” but I did try.

Let’s assume you want to put a rectangle with a drop shadow. Effectively if you break down a drop shadow you will find a black to grey gradient alpha mask of your rectangle, in easy words, nothing but a blurry grey scale representation of your rectangle lying back. Now, that’s what I tried out here. I took a rectangle, copied it behind it and kept it with a black and grey shades. I could’ve used just one gradient gray shaded rectangle but it doesn’t look that good.

Now, let’s see how that looks.

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Rectangle x:Name="tb1" Fill="Black" Opacity="0.2" Margin="1,3,0,0"  Height="{Binding Height, ElementName=tb5}" Width="{Binding Width, ElementName=tb5}"/>
            <Rectangle x:Name="tb2" Fill="Black" Opacity="0.2" Margin="-1,3,0,0"  Height="{Binding Height, ElementName=tb5}" Width="{Binding Width, ElementName=tb5}"/>
            <Rectangle x:Name="tb3" Fill="Black" Opacity="0.4" Margin="0,2,0,0"  Height="{Binding Height, ElementName=tb5}" Width="{Binding Width, ElementName=tb5}"/>
            <Rectangle  x:Name="tb4" Fill="Black" Opacity="0.2" Margin="0,3,0,0" Height="{Binding Height, ElementName=tb5}" Width="{Binding Width, ElementName=tb5}"  />
            <Rectangle Width="250" Height="100" x:Name="tb5" Fill="#FFE63939"  />
</Grid>

This is a very basic try of course. I’m going to make a usercontrol out of it somehow. And if I do, you will find it right here on my blog and looks like somehow I have to fake the blur too.

Well, until next time then. And by the way, it looks like below on the screen:
Rectangle Drop Shadow test

বাংলায় উইন্ডোজ ফোন – DelegateCommand, The Reusable ICommand

অনেকদিন পর ফেরত আসলাম। আজকের টিউটোরিয়াল ICommand এর একটি সহজ ও Reusable Implementation যার নাম DelegateCommand, তার উপরে। DelegateCommand implement হয় ICommand interface দিয়েই এবং এটি ICommand এর ব্যবহারকে অনেকটাই সহজ করে দেয়। আশা করি সবার ভালো লাগবে।

পুনশ্চ: যদি আপনি Introduction to ICommand দেখে না থাকেন তাহলে অনুগ্রহ করে দেখে আসুন।

 

প্রজেক্ট সোর্স পাওয়া যাবে এই লিংকে – http://sdrv.ms/1dYX3pT

উইন্ডোজ ফোন স্টোরে বাংলা অ্যাপ সাবমিশন – কি কি মনে রাখা উচিত

উইন্ডোজ ফোন স্টোরে যারা সাধারনত অ্যাপ পাবলিশ করছেন, অন্তত বাংলাদেশ থেকে, প্রথম প্রথম এই প্রশ্নটা মাথায় না আসাটা স্বাভাবিক কারণ সাধারণত অ্যাপগুলোর প্রধান ভাষা হয় ইংরেজী। কিন্তু উইন্ডোজ ফোন ৮ আসার পর লোকাল অ্যাপ নিয়ে কাজ করার প্রচলন টা লক্ষণীয়। এবং প্রথম যে প্রশ্নের সামনে আমরা পড়ি তা হচ্ছে, আমি কি করে একটি বাংলা অ্যাপ বানাবো এবং সেটা স্টোরে সাবমিট করবো। আমার আজকের উদ্দেশ্য এই প্রশ্নগুলোর উত্তর দেয়া।

বাংলা অ্যাপ বানানো:

বাংলা অ্যাপ বানানোর প্রথম সাবধানতা হচ্ছে যাদ আপনি সমগ্র অ্যাপটি বাংলায় করতে চান তাহলে অবশ্যই কোন নির্দিষ্ট ইউনিকোড ফন্ট (উদাহরণ: সিয়াম রূপালী) ব্যবহার করবেন সমগ্র অ্যাপটিতে । আপনি চাইলে উইন্ডোজ ফোনের ডিফল্ট ফন্ট যেটা আসে বাংলা লিখলে (নির্মলা) ব্যবহার করতে পারেন তবে নির্দিষ্ট কিছু যুক্তাক্ষরে সমস্যা হয় সুতরাং খেয়াল রাখবেন। অন্যক্ষেত্রে এটি দেখতেও বেশ সুন্দর, ব্যবহারেও বেশ ভালো।

অ্যাপ এর নাম অনায়াসে বাংলা দিতে পারেন। কোন সমস্যা নেই। তবে উইন্ডোজ ফোন ৭.৮ সহ টার্গেট করলে না দেয়া সমীচিন। তাতে উইন্ডোজ ফোন ৭.৮ এ আপনার অ্যাপ এর নাম দেখতে সমস্যা হবে।

খেয়াল রাখ‍বেন সার্চ কিওয়ার্ড এ আপনার অ্যাপ এর নাম এর সম্ভাব্য সকল ইংরেজী নাম দিয়ে দিতে। কেননা অাপনার অ্যাপ টি সার্চ করে তো পাওয়া লাগবে।

অ্যাপ এ যদি সার্চ রাখতে চান বাংলা চন্দ্রবিন্দু একমাত্র ভরসা এখন পর্যন্ত। কারো যদি দরকার হয় কাস্টম কন্ট্রোলটি, যোগাযোগ করুন আমার সাথে। 🙂 আমি সাধ্যমতো চেষ্টা করবো।

এইবার আসি লোকালাইজেশন এর কথায়। আপনি চাইলেই অ্যাপটি লোকালাইজড করতে পারেন। এ নিয়ে বিস্তারিত পাবেন এখানে । আপনার যদি একটি ইন্টারন্যাশনাল অ্যাপ থাকে যার কন্টেন্ট দেশ ও স্থান অনুসারে ভাষা বদলায়, তার জন্যে খুব ভালো অ্যাপ্রোচ এটি।

বাংলা অ্যাপ সাবমিশন:

বাংলা অ্যাপ সাবমিশন টা মোটেও কঠিন নয়। অনেকেই ভাবেন আমি লিখলাম সমগ্র অ্যাপ এর কন্টেন্ট বাংলায়। কিন্তু ভাষা দেখাচ্ছে স্টোরে এখনো ইংরেজী। কি করে ঠিক করি। আসুন দেখে নেই।

WMAppManifest

১. প্রথমে চলে যান আপনার সলুশ্যন এক্সপ্লোরার এর প্রোপার্টিজ এর মধ্যে WMAppManifest.xml এ। এর Packaging ট্যাব এ গেলে আপনি দেখতে পাবেন Default Language নামের ড্রপডাউন লিস্টে Bengali, Bengali (Bangladesh) এবং Bengali (India) আছে।

Capture 2

এবং নিচে খেয়াল করে দেখুন Supported Language নামক একটি লিস্ট আছে

Capture3খেয়াল করে দেখুন এখানেও Bengali, Bengali (Bangladesh), Bengali (India) আছে। আপনি Bengali এবং Bengali(Bangladesh) অবশ্যই চেক করে দিন এবং প্রয়োজনে Bengali (India) চেক করে দিন। কারণ আপনার সমর্থিত ভাষার উপর আপনার মার্কেট সিলেকশন নির্ভর করে । আপনি নিশ্চই চান না আপনার অ্যাপ টি কোন মার্কেটের কোন বাংলাভাষী থেকে দূরে থাকুক।

এবার আসুন Default language এর ব্যাপারে। অনেকেই আমাকে প্রশ্ন করেছেন যে যদি Default Language আমি বাংলা দেই তাতে সমস্যা কি? সমস্যা নেই। তবে পরবর্তীতে যখন অ্যাপ সাবমিট করবেন, মার্কেট সিলেকশনে শুধু বাংলা ভাষা সমর্থিত মার্কেট সিলেক্ট করতে হবে। নাহলে certification fail করতে পারেন। আর অনেকেই US market, UK market এ থাকেন দেশ ও দেশের বাইরে। আপনি নিশ্চই চান না আপনার অ্যাপ এর সম্ভাব্য গ্রাহক হারাতে। সুতরাং ডিফল্ট ল্যাংগুয়েজ ইংরেজী রাখুন।

তাহলে? যদি কেউ ভুল করে ডাউনলোড করে এবং না বুঝে বাজে রেটিং দেয়? সেজন্য অ্যাপ ডেসক্রিপশনে লিখে দিন “The official language for this app is bangla”. প্রথম লাইন হলে ভালো হয়। আর অবশ্যই একটি বাংলা বিবরণ রাখবেন। ভুলবেন না যেন। আর সার্টিফিকেশন কিন্তু অটোমেটেড প্রসেস না। সব কিছুই বেশ ভালো মতো পরীক্ষা করা হয়।

আশা করি সবার সব প্রশ্নের সমাধান হয়েছে।  🙂

 

Binding Command to custom Pushpin in Windows Phone 8 Map Control

Well, this one’s kind of out of line. I faced this last night, searched all over I can but I barely found a concise solution on this one.

Before we get into the solution, we need to see the problem we’re talking about. Shouldn’t we?

I was working with the new Windows Phone 8 Map Control provided with the sdk that allows here maps to be used in your app and I needed a bunch of Pushpins to be loaded in the map. So, Windows Phone Toolkit came to the rescue. I hooked up the <MapExtensions.Children> and added by pushpins there binded from my viewmodel.

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

            <maps:Map x:Name="MyMap" ZoomLevelChanged="MyMap_ZoomLevelChanged"  Loaded="MyMap_Loaded"   >

                <MapToolkit:MapExtensions.Children>

                    <MapToolkit:MapItemsControl Name="MapElements">
                        <MapToolkit:MapItemsControl.ItemTemplate>
                            <DataTemplate>
                                <MapToolkit:Pushpin Name="StopPushPin"  Style="{StaticResource MaximizedPushpin}"  Background="#B20000FF" Content="{Binding Name}" GeoCoordinate="{Binding Location}" Tap="Pushpin_Tap"  >
                                </MapToolkit:Pushpin>
                            </DataTemplate>
                        </MapToolkit:MapItemsControl.ItemTemplate>
                    </MapToolkit:MapItemsControl>
                    <MapToolkit:Pushpin Name="MyPushpin"  Content="I'm Here!" Background="#FF3CD303"  GeoCoordinate="{Binding MyLocation}" />
                </MapToolkit:MapExtensions.Children>

            </maps:Map>
        </Grid>

One could easily see here that I used a PushPin object as DataTemplate with a custom style attached. Lets check the style

<Style TargetType="MapToolkit:Pushpin" x:Key="MaximizedPushpin">

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="MapToolkit:Pushpin">
                    <Grid x:Name="ContentGrid" FlowDirection="LeftToRight">

                        <toolkit:WrapPanel Orientation="Vertical">

                            <Grid x:Name="grid" Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}" HorizontalAlignment="Left"
                                   RenderTransformOrigin="0.5,0.5" Height="148" Width="225">

                                <Grid.RowDefinitions>
                                    <RowDefinition Height="0.4*"></RowDefinition>
                                    <RowDefinition Height="0.015*"></RowDefinition>
                                    <RowDefinition Height="0.25*"></RowDefinition>
                                    <RowDefinition Height="0.015*"></RowDefinition>
                                </Grid.RowDefinitions>

                                <TextBlock Margin="8,4,4,4"
                                           FlowDirection="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FlowDirection}"
                                           Grid.Row="0" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
                                           TextWrapping="Wrap" FontSize="30">

                                </TextBlock>

                                <Border Grid.Row="1" Background="#CC474444" Margin="0,0,-6,0" />
                                <Grid Grid.Row="2"   MinHeight="31" Background="#EEF9F9F9" Margin="0,0,-8,0"  >
                                    <codefun:RoundButton Orientation="Horizontal" Foreground="Black" Background="Transparent"
                                                         BorderBrush="Black" ImageSource="/Assets/pushpin.get.direction.png"
                                                         HorizontalAlignment="Left" VerticalAlignment="Center"
                                                         Margin="0,2,0,0"
                                                         >
                                    </codefun:RoundButton>
                                </Grid>
                                <Grid Grid.Row="3"   Background="#99474444" Margin="0,0,-6,0"/>
                            </Grid>

                            <Polygon Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"
                                     Points="0,0 29,0 0,29"
                                     Width="29"
                                     Height="29"
                                     HorizontalAlignment="Left"/>
                        </toolkit:WrapPanel>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="PositionOrigin" Value="0,1" />
        <Setter Property="Background" Value="Black" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="FontSize" Value="30" />
    </Style>

All I wanted to do is to bind Command Parameter of RoundButton and hook a RelayCommand in my viewmodel. As is an attached property in the Map control I had to use FindAncestor mode when I tried to bind Command parameter in RoundButton. But bad news is it’s not supported in Windows Phone. The only relative binding mode I have here is templatedparent and self.

And I started looking for a solution. Then this came to my eyes and I was really happy. So, I followed as per what was written in there and voila!

I binded the Command with CommandParameters the following way.

<codefun:RoundButton Orientation="Horizontal" Foreground="Black" Background="Transparent"
                                                         BorderBrush="Black" ImageSource="/Assets/pushpin.get.direction.png"
                                                         HorizontalAlignment="Left" VerticalAlignment="Center"
                                                         Margin="0,2,0,0"
                                                         CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}"
                                                         >

                                        <BindHelper:BindingHelper.Binding>
                                            <BindHelper:RelativeSourceBinding
                                                Path="GetDirectionToPushPinCommand"
                                                TargetProperty="Command"
                                                RelativeMode="ParentDataContext"
                                                />

                                        </BindHelper:BindingHelper.Binding>
                                    </codefun:RoundButton>

A handy tool indeed!

বাংলায় উইন্ডোজ ফোন – Introduction to ICommand

ফিরে আসলাম আবার। আজকের টিউটোরিয়াল ICommand এর উপরে। নিঃসন্দেহে  অত্যন্ত গুরুত্বপূর্ন একটি interface যেটা MVVM approach এ বড় ভূমিকা পালন করে। আশা করি সবার ভালো লাগবে। 🙂

স্যাম্পল প্রজেক্ট ডাউনলোড করে নিন নিচের লিঙ্ক থেকে :
http://sdrv.ms/1eouqSL

Data Binding – The last words

Well, as the title says this would be my last points on Data Binding. That doesn’t actually mean this is all there is in data binding. Kindly consider I only could share two or three lines from the preface of the book named “Data Binding”. But as we need to move forward I’m only sharing what’s essential to know.

So, back with the same example we had in our last post. If we remember things correctly we left the work at this stage:

wp_ss_20130929_0001

If we remember correctly we used the button Update Data to update the data from C# code behind. What if we want to write something in the textboxes and want to update the data by clicking the button Update Data. Only this time the new Data would be what I write in the textboxes.

So, lets see what we did before first approach that might come to your head is to write something like this:

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            _personModel.Name =Name.Text;
            _personModel.Age = Age.Text;
            _personModel.Height = Height.Text;
        }

Well, I don’t blame you. It’s fair to do so. But if we don’t want the button, we just want to type and it will update automatically? Well, I know, who wants that ? :\

But what if it’s a data field and we have next button to go to another field like we do have in installation wizards, we don’t need a update button in that case. So, lets rename the Update button to Read Data so we can check that the data is updated truly.  So, lets change the button name and change the “Button_Click” event as following:

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Name.Text = _personModel.Name;
            Age.Text = _personModel.Age;
            Height.Text = _personModel.Height;
        }

So, now it would read the data instead of writing it. Then who is going to write it! :\
Well, lets change the data binding mode to TwoWay and we’re done for the updating!


<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   <TextBox Height="70" HorizontalAlignment="Left" Margin="0,130,0,0" Name="Name" Text="{Binding Name, Mode=TwoWay}" VerticalAlignment="Top" Width="450" />
   <TextBox Height="72" HorizontalAlignment="Left" Margin="0,206,0,0" Name="Age" Text="{Binding Age, Mode=TwoWay}" VerticalAlignment="Top" Width="450" />
   <TextBox Height="72" HorizontalAlignment="Left" Margin="0,284,0,0" Name="Height" Text="{Binding Height, Mode=TwoWay}" VerticalAlignment="Top" Width="450" />
   <Button Content="Read Data" Click="Button_Click" Margin="0,361,0,159" ></Button>
</Grid>

You see what I did here is, I changed the Text Property of the Name TextBox control to Text=”{Binding Name, Mode=TwoWay}” and I changed all the TextBoxes accordingly allowing it to update the underlying data automatically when it’s changed. 🙂 No need for an update button.

DON’T USE IT IF YOU DON’T WANT TO CHANGE THE UNDERLYING DATA WITHOUT ANY CONFIRMATION.

So, you see the amazing thing here is all I changed is the binding mode. If I didn’t have to read this using the button we wouldn’t have needed any code practically.

Now Let’s get to see Element Binding a bit

Well, to demonstrate element binding what are we going to do is, we’re gonna put a slider control in our ContentPanel. Whenever we change the value of the slider we want to see that in a TextBlock. So we will get rid of all the textboxes and we will  insert a slider in our Windows Phone project.

Slider and Textblock

So, you see, we added a TextBlock and a slider below and removed the button and textboxes that were here before.

So, our ContentPanel looks like this now.

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Height="70"
                     HorizontalAlignment="Left"
                     Margin="10,130,0,0"
                     Name="ValueBox"
                     Text="TextBlock"
                     FontSize="36"
                     VerticalAlignment="Top"
                     TextAlignment="Center"
                     Width="436" />
            <Slider x:Name="HSlider" Orientation="Horizontal"
                    HorizontalAlignment="Left"
                    Height="172"
                    Margin="10,200,0,0"
                    VerticalAlignment="Top"
                    Width="436"
                    LargeChange="10"
                    SmallChange="1"
                    Minimum="0"
                    Maximum="100"
                    Value="50"

                    />
        </Grid>

Lets look at the xaml for a minute. You will see the slider named HSlider has a horizontal orientation and Minimum and Maximum value set from 0 to 100. What we want is we want to see the slider value on the textblock above, it should change as we change the slider. What’s the first approach comes to your mind. We can set a ValuChanged event in the slider and show the value in the textblock like this.

Adding a ValueChanged event in the XAML:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Height="70"
                     HorizontalAlignment="Left"
                     Margin="10,130,0,0"
                     Name="ValueBox"
                     Text="TextBlock"
                     FontSize="36"
                     VerticalAlignment="Top"
                     TextAlignment="Center"
                     Width="436" />
            <Slider x:Name="HSlider" Orientation="Horizontal"
                    HorizontalAlignment="Left"
                    Height="172"
                    Margin="10,200,0,0"
                    VerticalAlignment="Top"
                    Width="436"
                    LargeChange="10"
                    SmallChange="1"
                    Minimum="0"
                    Maximum="100"
                    Value="50"
                    ValueChanged="HSlider_ValueChanged_1"
                    />
        </Grid>

and write the event handler behind in MainPage.xaml.cs like this:

private void HSlider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs e)
        {
            if(HSlider!=null)
                this.ValueBox.Text = HSlider.Value.ToString();
        }

And if you build this and run it on the emulator or device, whenever you change the slider you will see it’s value in the textblock. But is that we wanted here? NOOOO!!

Let’s make things a bit simple. If we can bind the slider to textblock item we can instantly show the slider value on the textblock. No code needed whatsoever! And why we bind the slider to the textblock. Because here the textblock shows the data so the slider works here as the model and the textblock as view! So, the model is binded to the view!

Let’s chill and see the easiest trick here. Now our ContentPanel looks like this and we have got rid of the event handler named HSlider_ValueChanged_1 from MainPage.xaml.cs

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Height="70"
                     HorizontalAlignment="Left"
                     Margin="10,130,0,0"
                     Name="ValueBox"
                     Text="{Binding Value, ElementName=HSlider}"
                     FontSize="36"
                     VerticalAlignment="Top"
                     TextAlignment="Center"
                     Width="436" />
            <Slider x:Name="HSlider" Orientation="Horizontal"
                    HorizontalAlignment="Left"
                    Height="172"
                    Margin="10,200,0,0"
                    VerticalAlignment="Top"
                    Width="436"
                    LargeChange="10"
                    SmallChange="1"
                    Minimum="0"
                    Maximum="100"
                    Value="50"

                    />
        </Grid>

See, the change we made here is that we changed the text property of the textblock into Text=”{Binding Value, ElementName=HSlider}” . Here, we binded the Value property of the Element HSlider.

😀 See? It’s really easy and see how much clean it looks now, all our job is done by only one line. That’s the magic of data binding.
wp_ss_20131004_0002

So, this is it for now, Next we’re gonna talk a little about DataConverters. Till then ciao!