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

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

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

 

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

Advertisements

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

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

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

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

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

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

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

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

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

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

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!

Uri Unsafe Characters problem – Image Upload in Windows Phone 7

As of the title may suggest, you might have an impression at the very beginning, that why the heck someone would possibly think of uploading images to Windows Phone 7 at this era of Windows Phone (it’s been almost a year since Windows Phone 8 is out there in the market, right?). The thing is, actually it was the requirement of my employers. Now without further ado, let’s jump over to our main talk.

My scenario: we have been working on a socializing app for quite a long time, me with my partner Ashekul Islam Khan was appointed on the WP client side. I was trying to upload photo from my WP client to a Java server. If you have a problem uploading image in WP and Bing it, I guess there would be tons of search results. More or less we have tried to use all of them, but the disappointing fact was none of them seemed to work.

First thing first the byte representation of these two platforms are not the same (in c# it’s unsigned, while in java it’s signed). So we decided to send data over String format. We tried to use base64 strings. We tried image upload from WP client to .NET server, it worked just fine. But approaching different server had some problems. The string base64 converted data we sent over an Uri and the server side received data seemed exactly same at a first glance, but after a while we found there are actually three characters that are not exactly the same on both sides. That’s when we found the fact of Uri unsafe characters (Uri strings as defined by RFC 3986). For that we needed to do something extra, encode and put some Uri safe characters from client side and do the exact opposite to get the bas64 string back on the server side.

Client side encoded data:

static string base64urlencode(byte[] arg)
{
string s = Convert.ToBase64String(arg); // Regular base64 encoder
s = s.Split('=')[0]; // Remove any trailing '='s
s = s.Replace('+', '-'); // 62nd char of encoding
s = s.Replace('/', '_'); // 63rd char of encoding
return s;
}</code>

Server side decoded data:

<code>static byte[] base64urldecode(string arg)
{
string s = arg;
s = s.Replace('-', '+'); // 62nd char of encoding
s = s.Replace('_', '/'); // 63rd char of encoding
switch (s.Length % 4) // Pad with trailing '='s
{
case 0: break; // No pad chars in this case
case 2: s += "=="; break; // Two pad chars
case 3: s += "="; break; // One pad char
}
return Convert.FromBase64String(s); // Standard base64 decoder
}

And you will need a PhotoChooserTask  to select and get photo data. We have also implemented it on a php server and its working just fine (yes, of course you have to write some script on the php server side J). I will get back to you guys with complete codes. For the time being, its TaDa.

Now thanks giving: it’s been a real honor that Swagata let me write something in this blog. Poitta, I owe you some candy! 🙂