Quantcast
Channel: Corrado's Blog 2.0
Viewing all 46 articles
Browse latest View live

Behaviors for Xamarin Forms v2.0

$
0
0

I’ve pushed version 2.0 of my behavior implementation for Xamarin Forms and moved it to a new location on GitHub: https://github.com/corradocavalli/Corcav.Behaviors

The reason for this is that, in order to prevent conflict with Xamarin API I’ve renamed the root namespace so upgrading to this version will break your code and I’m really sorry for this, but I’m sure it won’t take too long to fix it.

I’ve also removed old nuget package and replaced with this one : ’https://www.nuget.org/packages/Corcav.Behaviors/

Version 2.0 uses Xamarin Forms 1.3.4 and Unified API project as iOS demo.

Sorry for breaking your code, my fault using Xamarin as assembly name Sad smile (lesson learned), honestly didn’t expect such success, and I thank you for that.


Visual Studio 2013: Fixing NuGet package install error in Xamarin Android projects

$
0
0

Recently, quite often indeed, I’m facing an issue trying to add some NuGet packages to a Xamarin Android project, in this particular case I was trying to add Xamarin.Android.Support.RecyclerView package.

image

The error I get after clicking Install is:

image

Some search on the internet provided me some solutions, the one working for me is changing Android version option from:

image

to an explicit value (API 21 in my case)

image

after this change, all packages get installed properly.

Application wide resources (reloaded)

$
0
0

Back in September 2014 I blogged about adding application wide resources to Xamarin Forms applications, that technique is no longer needed since starting from v 1.3 Xamarin added support to app wide resources into Xamarin Forms core.

So what it this post about? It is about adding (and using) them in a more user-friendly way.

Since v 1.3 you can create a resource that can be reachable from all pages this way:

public class App : Application
    {
        public App()
        {
            this.Resources = new ResourceDictionary
            {
                {"TextColor", Color.FromHex("00FF00")}
            };

            // The root page of your application
            this.MainPage = new MainView();
        }
    }

And use the resource from a XAML page this way:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App1.MainView">
    <Label Text="Hello from Xamarin Forms" 
             VerticalOptions="Center" 
             HorizontalOptions="Center" 
             TextColor="{StaticResource TextColor}" />
</ContentPage>

Ok, It works but is not very friendly, resource name is not listed in XAML Intellisense (powered by Resharper of course) and as XAML lover I’d like to define my application resources in XAML the same way I do in a page.

Luckily you can and it’s very easy:

1- Delete App.cs file

2-Add a new Forms XAML Page and name it App.cs

image

3-Make App.cs inherit from Application instead of ContentPage

public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }

4-Replace the generated XAML with following one, don’t forget to substitute [YourNamespaceHere] with your own’s application namespace

<Application xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="[YourNamespaceHere].App">
    <Application.Resources>
        <ResourceDictionary>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Your project should now look like this:

image

and you can add your resources inside ResourceDictionary as in following example:

<Application xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="[YourNamespaceHere].App">
    <Application.Resources>
        <ResourceDictionary>
            <Color x:Key="TextColor">Red</Color>
        </ResourceDictionary>
    </Application.Resources>
</Application>

And now, your resource will work as expected but it will also be listed by Intellisense

image

Definitively more friendly than using code (IMHO)

Hope to see this feature added to Xamarin Forms template soon.

Adding a splash screen to Xamarin Forms apps

$
0
0

Every Xamarin Forms app should ship with a splash screen, it is the first thing a user see and it contributes to reduce the perceived application boot time.

Adding one is quite easy, let’s go from simpler to harder.

The simpler: Windows Phone

Just replace SplashScreenImage.jpg (720×1280 pixels) with your own app launch image in the Windows Phone project and you’re done.

image

The harder: iOS

If you follow iOS documentation you’ll know that adding your own launch screen is just a matter of adding the proper images to the project via info.pList options.

image

unfortunately once you do that you’ll still see the blue background with Xamarin Logo at startup, to fix it delete the content of Launch Storyboard option into info.pList and you’re done (no idea why template adds that storyboard inside Resources folder)

image

The hardest: Android

Adding a splash screen requires following steps:

image

1-Add the splash screen image into Resources\drawable folder (and all the variants you want to support) in previous screenshot file is named splash.png

2-Create a new folder under Resources and name it values

3-Add an xml file into values folder (name is not important, in my case I named it Styles.xml)

4-Add this content to xml file

<?xml version="1.0" encoding="utf-8" ?>
<resources>
    <style name="Theme.Splash" parent="android:Theme">
        <item name="android:windowBackground">@drawable/splash</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>

5-Add a new activity to the project and add this code (of course you can safely remove the delay before StartActivity method)

[Activity(Theme = "@style/Theme.Splash", //Indicates the theme to use for this activity
             MainLauncher = true, //Set it as boot activity
             NoHistory = true)] //Doesn't place it in back stack
    public class SplashActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            System.Threading.Thread.Sleep(3000); //Let's wait awhile...
            this.StartActivity(typeof(MainActivity));
        }
    }

6-Remove the MainLauncher=true from original activity since this is the new activity that will be launched at startup.

Hope this helps…

Blend 2015: Cannot add additional fields to a type… error

$
0
0

Yesterday repaved my machine and installed Windows 10 and Visual Studio 2015, I then loaded one of the projects I’m working on and I’ve a been shocked to discover that none of my views was rendering in Blend 2015 because of this error: “Cannot add additional fields to a type that does not have a constructor”

image

Thanks to Blend team I was pointed to a workaround that fixed it (at least for me)

Go to Tools->Options->XAML designer and check the option: Run project code in XAML Designer (if supported) and reload the project

image

 

Hope it helps.

Dynamic localization of Windows Store apps

$
0
0

Localizing a Windows Store app is a fairly easy task thanks to the x:UId attribute introduced with WinRT.
If you need to create a Multilanguage application just add to your Visual Studio solution a folder named Strings and below it add a folder for each language you want to support using the two letter ISO language as name.
In this picture I have a solution that support Italian and American English

image

Inside each folder I’ve added a resource file and note that there’s a Resource.resw file just below Strings folder, it represent the default fallback resource language file that will be used in case your app will be executed on a system whose language is different than America English or Italian.

Inside each Resource.resw add the property of the control to localize, in our case we want to localize the Text property of a TextBlock, so the file content for each will be:

en-US folder

image

it-IT folder

image

Now to localize the Text property of our TextBlock all we need to to is use this XAML:

1 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 2 <TextBlock x:Uid="WelcomeMessage" 3 VerticalAlignment="Center" 4 Foreground="BlueViolet" 5 Text="..." 6 HorizontalAlignment="Center" 7 FontSize="48" /> 8 </Grid>

Here’s what you’ll see when the code is executed on an Italian pc:

image

Very easy isn’t it? Smile

This approach let you do more than just localize Text, if you want to dig more into it you can read this article

Ok, but imagine you have this mandatory requests:

  • 1-Application language can be unrelated to machine language (French app running on an Italian machine)

2-Language switching should not require an application reboot

3-You must use a MVVM friendly solution

Ok, things can get a little more intricate here  and since I haven’t found a standard solution I solved this way:

Step 1: Since we’ll deal with text only let’s rename resources inside .resw files from WelcomeMessage.Text to just WelcomeMessage (see below)

image

Step 2: Let’s create a ViewModel (yes, MVVM always requires a ViewModel…) and let’s add the necessary code to load the strings dynamically:

1 public class MyViewModel : INotifyPropertyChanged 2 { 3 private ResourceContext resoureContext; 4 5 public MyViewModel(string language) 6 { 7 this.UpdateCulture(language); 8 } 9 10 public void UpdateCulture(string language) 11 { 12 this.resoureContext = ResourceContext.GetForCurrentView(); 13 this.resoureContext.Languages = new List<string> { language }; 14 } 15 16 public string GetResource(string stringResource) 17 { 18 try 19 { 20 var resourceStringMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources"); 21 return resourceStringMap.GetValue(stringResource, this.resoureContext).ValueAsString; 22 } 23 catch (Exception ex) 24 { 25 return $"?{stringResource}?"; 26 } 27 } 28 29 ... 30 }

The magic here is inside UpdateCulture and GetResource methods, if we name the TextBlock in previous XAML snippet MyTextBlock we can dynamically change its text using this code:

1 public sealed partial class MainPage : Page 2 { 3 public MainPage() 4 { 5 this.InitializeComponent(); 6 this.MyTextBlock.Text = new MyViewModel("it-IT").GetResource("WelcomeMessage"); 7 8 } 9 }

But since we’re using MVVM we want to use databinding for that instead of code and we need a smart solution otherwise localization can become tedious, solution is not very far: just use an indexer:

Just add this line of code to the ViewModel

1 public string this[string key] => this.ApplicationController.GetResource(key);

And let’s inform binding that our indexer property need to be refreshed so that all texts will be reloaded when user changes the UI language at runtime modifying the UpdateCulture method this way:

1 public void UpdateCulture(string language) 2 { 3 this.resoureContext = ResourceContext.GetForCurrentView(); 4 this.resoureContext.Languages = new List<string> { language }; 5 this.OnPropertyChanged("Item[]"); 6 }

Note the trick of using “Item[]” as property name to signal that the class indexer has changed.

So let’s bind TextBlock’s Text property to viewmodel indexer using this syntax, and you’re done.

1 <TextBlock x:Name="MyTextBlock" 2 VerticalAlignment="Center" 3 Foreground="BlueViolet" 4 Text="{Binding [WelcomeMessage]}" 5 HorizontalAlignment="Center" 6 FontSize="48" />

You can find a complete example here.

Have fun!

Genymotion issue with Windows 10 10586

$
0
0

I use Genymotion for my Xamarin Android development, I know that both Xamarin and Microsoft provide their own emulator but, for my machine configuration Genymotion is the one I like most at the moment.

This post is to help you find a solution in case the virtual device doesn’t boot on a machine after the upgrade to TH2 aka build 10586, with this message:

image

obviously the message is meaningless, digging into device log file located at %LocalAppData%\Genymobile\Genymotion\deployed\  I’ve discovered that error depends on a network issue:

0:00:01.362237 VMSetError: Failed to open/create the internal network ‘HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter #4′

After doing several test and internet search I finally found the reason of the problem: no idea why but an option in the adapter settings was not selected:

image

The option is: VirtualBox NDIS6 Bridged Networking adapter, if not selected, select it and try again, your emulator should now work (or at least, it worked for me)

works-on-my-machine-starburst

 

Hope it works for you too, otherwise good luck finding the solution, if you find it please share, Genymotion support for free licenses is far than optimal.

Change ListView RowHeight programmatically in Xamarin Android

$
0
0

Here’s a quick code snippet that allows you to change the row height of an Android ListView in Xamarin

public override View GetView(int position, View convertView, ViewGroup parent) { View view = convertView ?? this.context.LayoutInflater.Inflate(Android.Resource.Layout.ActivityListItem, null); if (view.LayoutParameters == null) { view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, 300); } else { view.LayoutParameters.Height = 300; } ...other code here... return view; }

Code resides inside ListView adapter, as you see, the magic is acting on view LayoutParameters property.

Hope it helps.


Fixing SDWebImage issue on Xamarin.iOS

$
0
0

Loading an image into an ImageView control using Xamarin.iOS is a straightforward process:

  • Add a ImageView to a ViewController and give it a name (e.g: MyImage)
  • Add an image to Resources folder (e.g Users.png) and be sure that related Build Action is set to BundleResource.
  • And add this code:
        public override async void ViewDidLoad() { base.ViewDidLoad(); MyImage.Image=UIImage.FromBundle("Users.png"); }

      And you’re done, as alternative you can also use UIImage.FromFile, in this case the call is asynchronous and doesn’t use caching, while former is synchronous and does caching.

      Ok, but what if I want to show an image from a web url? things gets more complicated since you have to do the entire downloading process manually, something like:

      public async Task<UIImage> FromUrl(string imageUrl) { var httpClient = new HttpClient(); var contents = await httpClient.GetByteArrayAsync(imageUrl); return UIImage.LoadFromData(NSData.FromArray(contents)); }

      And use it this way:

      MyImage.Image = await this.FromUrl("http://thechromenews.com/wp-content/uploads/2015/11/Apple-Logo-4.png");

      Cool, but what if I want to use caching, show a placeholder or fire some code when downloading completes? well, that’s more code to write and since this is a quite common task you’ll be happy to know that there’s a component that does that for you.

      Look for SDWebImage on Xamarin Component Store and add it to your project:

      image

      Doing that adds to ImageView control a SetImage extension method that accepts a Uri and does all the work for you, usage is very easy, just write something like:

      NSUrl url=new NSUrl("http://thechromenews.com/wp-content/uploads/2015/11/Apple-Logo-4.png"); MyImage.SetImage(url,null,null);

      If you try this code you’ll discover that it doesn’t work, why? is the component buggy? well no, if you try it on older iOS versions it works fine.

      Also this quite common alternative raises an exception on iOS 9.x

      private UIImage FromUri(string uri) { using (var url = new NSUrl(uri)) using (var data = NSData.FromUrl(url)) return UIImage.LoadFromData(data); }

      Ok, so what is the problem? well Apple decided that starting from iOS 9.0 all communications must use ATS (app transport security) and if you want to change this behavior you have to add an entry into info.plist file.

      This blog post describes ATS in detail and I encourage you to read it: http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

      To cut a long story short: Add this entry to your info.plist

      <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

      And everything will work as expected. Smile

      HTH

      Use IDEA IDE for Android UI design with Visual Studio and Xamarin

      $
      0
      0

      While Xamarin did a monster job integrating Android and iOS designers in both Visual Studio and Xamarin Studio as soon as your project becomes larger you’ll soon hit their limitations, that why many pro developers end up using native designers for UI design. This post is about how to use IntelliJ IDEA based IDEs for Android UI design together with Visual Studio, following the same approach we use with Blend for Windows development.

      Step 1: install your favorite IDE: Android Studio or IntelliJ IDEA (they’re practically the same since Android Studio is based on IntelliJ IDEA)

      Step 2: Install XamarIdea extension for Visual Studio, this extension, recently updated for Visual Studio 2015, will make integration between the two IDEs a lot faster, thanks to Egor Bogatov (@EgorBo) for sharing.
      No idea if something similar exists for Xamarin Studio (sorry, I’m not an pro Xamarin Studio user)

      Step 3: Create a new blank Android app using Visual Studio

      image

      and wait until initial project skeleton creation process ends.

      Step 4: Right-click the Main.axml file inside Resources\layout folder and you should see a new option: Open in IDEA/Android Studio

      image

      click it and you’ll get an initial configuration dialog that should point to IDEA/Android Studio path, if not select it manually, together with other plugin options

      image

      click Ok, and you’ll see a warning dialog saying that your project needs some modifications:

      image

      These modifications are necessary since Android layout files use a different extension (.xml) and project structure is slightly different than Xamarin Android apps, just say yes; unfortunately these changes will prevent you to use the integrated Xamarin Android designer further unless you rename the layout file back to .axml. Click Yes, and you’ll get a final dialog reminding you to recompile your project inside Android IDE and that plugin options are available under Visual Studio’s Tools menu:

      image

      Step 5: Switch to IDEA IDE and, for sure, rebuild the project

      image

      On the left you’ll see the project structure, under app node expand the Resources folder and you’ll see the familiar Android folder structure together with your renamed main.xml file.

      image

      Double click it to open the designer.

      image

      I won’t go into design detail since there are lots of demo tutorials on JetBrains’s site, just want you to see some of the plus of IDEA and why it is more productive than Visual Studio’s integrated editor/designer.

      Step 5: Design

      -Select and delete the autogenerated button from design surface.
      -Let’s change root LinearLayout to a RelativeLayout using the Component tree window in the upper right corner.

      image

      -Drag a Plain Text to design surface until top tooltip shows CenterVertical/CenterHorizontal

      image

      -Set layout_width to match_parent using Properties window (hint: if you need to search for a property just start typing to select matching properties Smile)

      -Let use xml editor to add left and right margins: Switch to text, select the EditText and start typing: ma, YES! full intellisense to the rescue!

      image

      -Do you want to create a style that you can reuse with others EditTexts? just right click the edit text and use Refactor –> Extract Style menu

      image

      Select the properties you want to export (this dialog will look familiar to Reshaper users) and click OK

      image

      the layout xml has been changed to:

      <EditText android:id="@+id/editText" style="@style/MyEditTextStyle"/>

      and a styles.xml file has been created for you under values folder:

      image

      Of course you can edit the styles.xml file with full intellisense / editors support

      image

      Step 6-Back to Visual Studio

      Save the project and switch back to Visual Studio, your main.xml file is automatically updated, but unfortunately the new files that have been added to the project, like styles.xml in our demo, must be added manually to the project.

      Add styles.xml under values folder, compile and continue developing your app using Visual Studio.

      Closing:

      I’ve just scratched the surface of IDEA design productivity features, I encourage you to give it a try, I’m sure you’ll love it.

      Have fun exploring!

      PS: Did I tell you that IDEA renders AppCompat’s widgets instead of a boring dark gray box? Winking smile

      XAML relative binding trick

      $
      0
      0

      MVVM newcomers find creating a UI like this (a simple ListView containing a button that removes current row) quite intricated.

      image

      This because, while you can add a command to the item bound to each row, it’s more convenient to have a common DeleteCommand on parent ViewModel that accepts the Item to remove from the collection feeding the list.

      Here’s our ViewModel:

      public class MyViewModel { private RelayCommand<ReportUnit> deleteCommand; public MyViewModel() { this.Items = new ObservableCollection<ReportUnit>(); for (int i = 0; i < 10; i++) { this.Items.Add(new ReportUnit() { Name = $"Item {i}" }); } } public RelayCommand<ReportUnit> DeleteCommand { get { return this.deleteCommand ?? (this.deleteCommand = new RelayCommand<ReportUnit>((o) => { this.Items.Remove(o); })); } } public ObservableCollection<ReportUnit> Items { get; private set; } } public class ReportUnit { public string Name { get; set; } }

      And here’s the page XAML:

      <Page x:Class="DemoBinding.MainPage" 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"> <Page.Resources> <Style x:Key="ListItemContainerStyle" TargetType="ListViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> </Style> </Page.Resources> <Grid x:Name="RootGrid"> <ListView ItemsSource="{Binding Items}" ItemTemplate="{StaticResource MyItemTemplate}" ItemContainerStyle="{StaticResource ListItemContainerStyle}"> </ListView> </Grid> </Page>

      The “magic” is of course inside MyItemTemplate:

      <DataTemplate x:Key="MyItemTemplate"> <Grid d:DesignWidth="568.775" Height="80" d:DesignHeight="100"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> <TextBlock TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Center" FontSize="26.667" /> <Button Grid.Column="1" Content="Delete" HorizontalAlignment="Stretch" Command="{Binding DataContext.DeleteCommand, ElementName=RootGrid}" CommandParameter="{Binding}" VerticalAlignment="Stretch" Margin="5" /> </Grid> </DataTemplate>

      As you see, the  button ‘steal’ the DataContext of RootGrid element and invokes MyViewModel’s DeleteCommand while passing its own DataContext as CommandParameter.

      Simple and clean. Smile

      Xamarin Forms preview with Gorilla Player

      $
      0
      0

      One of the major complaints about Xamarin Forms is the lack of designer with relative preview so, at the time of this writing, the development process is made up of a continuous sequence of: write XAML, deploy, see result, stop, edit XAML and try again, not a very convenient and productive way to work Sad smile

      GorillaPlayer is a tool from a company named UXDivers that provides real time XAML preview on any Emulator/Simulator speeding up development process.

      Note: GorillaPlayer is actually in beta and available via invite only, go request your invite here: www.gorillaplayer.com the player is available for both Visual Studio and Xamarin Studio (both Windows and iOS)

      Once you get the invite, download the installer for your platform, enter the invitation code and let the installer complete installation, I encourage you to select the “Install Player + SDK + Samples” option since it contains a fundamental component (a.k.a. The Player)

      image
      If everything goes well, you should now have a new element in your tray area (on Windows Platform)

      image

      Right clicking the icon you’ll see all Gorilla Player’s options, I suggest you to have a look at Getting Started Walkthrough

      image:

      In order to see your XAML output you must install the Gorilla Player App in target emulator/simulator (in alternative using included Gorilla Player’s SDK, the player can be integrated directly in your app, see SDK page for more details) the player will try to connect with the host running on your machine

      image

      and once connection is completed (you have both automatic and manual setup options)  you’ll see the monkey smiling and ready to render your XAML

      image

      Let’s see some XAML then!

      While the player app is running, create a brand new Xamarin Forms app (or open an existing one…) and open/add a XAML page, you should see the preview live on the emulator/simulator, if not check Gorilla Player’s option under: Tools->Gorilla Player (in Visual Studio) if not connected select the Connect option and check Follow me option

      image

      Note: using Stick to this XAML will let you freeze the rendered XAML while working on another file.

      If Gorilla can’t render your XAML you’ll see an error message like this:

      image

      Otherwise you’ll get the final output, here’s a demo XAML fragment:

      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="GorillaTest.Views.MyView"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="MyLabelStyle" TargetType="Label"> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="VerticalOptions" Value="CenterAndExpand" /> <Setter Property="FontSize" Value="20" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout BackgroundColor="Teal"> <Image Source="icon.png" WidthRequest="100" HeightRequest="100" /> <Label Text="Gorilla Player Rocks!" Style="{StaticResource MyLabelStyle}" TextColor="White" /> </StackLayout> </ContentPage>

      image

      As you see the Player supports every XAML element including Images, Styles, Resources, etc it also support ContentViews (see here)

      But what about design time data? : If you have a ListView I presume you want to see how it renders at runtime right? luckily Gorilla Player has a great support for design time data too, with several options (see here) probably the quickest one is to use add a json file with sample data to your project.

      Let’s take this XAML as example (taken from Gorilla’s demo MyCoolCompanyApp)

      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyCoolCompanyApp.MyPeople" xmlns:common="clr-namespace:UXDivers.Artina.Player;assembly=UXDivers.Artina.Player.Common" BackgroundColor="#455a64" xmlns:local="clr-namespace:MyCoolCompanyApp;assembly=MyCoolCompanyApp"> <ContentPage.Content> <Grid> <Image Opacity="0.5" x:Name="img" Source="bridge_bg.png" Scale="1.5" Aspect="AspectFill"/> <StackLayout Padding="10,30,20,0"> <ListView ItemsSource="{Binding .}" SeparatorVisibility="None" BackgroundColor="Transparent" SeparatorColor="#DFDFDF" HasUnevenRows="false" RowHeight="120"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <local:MyPeopleTemplate /> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </Grid> </ContentPage.Content> </ContentPage>

      The output rendered by Gorilla Player is:

      image

      Awesome! but since we are at design time, were do the ListView data come from? If you look at PCL project you’ll see that it includes a SampleData.json file

      image

      with this content:

      { "MyPeopleTemplate.xaml": { "Name": "John Silverstain", "City": "MELBOURNE", "Department": "Marketing", "Color": "Red", "Age": 29, "Followers": 243, "Photo": "friend_thumbnail_27.jpg" }, "MyPeople.xaml": [ { "Name": "John Silverstain", "City": "MELBOURNE", "Department":"Marketing", "Color":"Red", "Age":29, "Followers":243, "Photo":"friend_thumbnail_27.jpg" }, { "Name": "Pam Tailor", "City": "SIDNEY", "Department":"Design", "Age":32, "Followers":24, "Photo":"friend_thumbnail_75.jpg" }, { "Name": "Casy Niman", "City": "HOBART", "Department":"Accounts", "Age":58, "Followers":267, "Photo":"friend_thumbnail_93.jpg" }, { "Name": "Gorge Tach", "City": "NEWCASTLE", "Department":"Design", "Age":29, "Followers":127, "Photo":"friend_thumbnail_55.jpg" }, { "Name": "Cristina Maciel", "City": "HOBART", "Department":"Mobile Dev.", "Age":32, "Followers":80, "Photo":"friend_thumbnail_31.jpg" }, { "Name": "Simon Deuva", "City": "MELBOURNE", "Department":"Media", "Age":58, "Followers":420, "Photo":"friend_thumbnail_34.jpg" } ] }

      As you see, the file contains a set of sample data, in json format, that will be associated to each page (MyPeopleTemplate.xaml and MyPeople.xaml in this case) ideally simulating the same data that the associated ViewModel will provide at runtime. in the docs you’ll find alternative design time solutions like using a Json data class or a Plain object.

      While in beta, the product is already very stable and a total life saver if you do Xamarin Forms development so I encourage you to give it a try and help the team fixing all issues so that we can get an official v 1.0 soon.

      Issues can be filed here.

      Happy Gorilla rendering! Smile

      Xamarin.Android Status bar color not set

      $
      0
      0

      Not a very descriptive title, but good for search engines Smile

      The problem: You’re using Xamarin.Android.Support.v7.AppCompat in order to have Material Design’s Toolbar available also devices running o pre-Lollipop (v.21) releases.

      You added a reference to the library:

      image

      Added the style:

      <style name="ParentMaterialTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="colorControlHighlight">#1ef1ab</item> <item name="colorButtonNormal">#f955f3</item> <item name="colorControlActivated">#0cf427</item> </style>

      Added the entry into AndroidManifest.xml:

      <application android:label="_02_StandaloneToolbar" android:theme="@style/MaterialTheme" />

      Created the toolbar:

      <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:minHeight="?attr/actionBarSize" android:theme="@style/ToolbarTheme" app:popupTheme="@style/PopupTheme" android:id="@+id/toolbar"> </android.support.v7.widget.Toolbar>

      Included into Main.axaml:

      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <include android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/toolbar"/> </RelativeLayout>

      But when you run it, the status bar doesn’t follow colorPrimaryDark but it remains black Confused smile

      image

       

      Solution: add this line into Activity’s OnCreate method (yes, you have to use code)

      this.Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);

      And you’re done!

      image

      Add a SnackBar to you Xamarin.Android app

      $
      0
      0

      Material design introduced a new lightweight way to provide feedback to a user, something that sits between the AlertDialog and Toast alternatiives with a funny name: SnackBar.
      A Snackbar appears at the bottom of the view and can optionally display an additional custom button.

      Here are the basic steps to show a SnackBar:

      -Open Visual Studio and create a new blank Android app

      -Using Nuget add the Xamarin.Android.Support.Design library, this will let you target Android releases older than v21

      image

      • -Using the code generated by the template, lets make the SnackBar appear when the default button is pressed.

      -Add this code inside MainActivity’s OnCreate method

      protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); // Get our button from the layout resource, // and attach an event to it Button button = FindViewById<Button>(Resource.Id.MyButton); button.Click += (s, e) => { //Creates the Snackbar Snackbar snackBar = Snackbar.Make(button, "Text", Snackbar.LengthIndefinite); //Show the snackbar snackBar.Show(); }; } }

      • -Compile the project and wait until build succeeds, be patient if operation takes more than than usual since this delay is due to the fact that the missing packages are downloading and their size is quite huge. If you stop compilation download will fail and you’ll start having a lot of “…invalid zip” error. in this case delete the zip folder mentioned on error message and try again.
      • -You’ll now see this error message:
      • image
      • -Let’s fix it adding the required theme (you can create your own deriving from Theme.AppCompat of course)
        [Activity(Label = "TestSnackBar2", MainLauncher = true, Icon = "@drawable/icon", Theme = "@style/Theme.AppCompat")]

      • -Run the project again and you’ll see this bar appear at the bottom of the view
      • image
      • -Quite sad indeed, luckily the SnackBar can be customized, so let’s add more code:
      button.Click += (s, e) => { //Creates the Snackbar and subscribes the button press event Snackbar snackBar = Snackbar.Make(button, "Text", Snackbar.LengthIndefinite).SetAction("Ok", (v) => { Console.WriteLine("Done"); }); //set action button text color snackBar.SetActionTextColor(Android.Graphics.Color.Green); //Set action button text size TextView txtAction = snackBar.View.FindViewById<TextView>(Resource.Id.snackbar_action); txtAction.SetTextSize(Android.Util.ComplexUnitType.Dip, 18); //Set message text size and color TextView txtMessage = snackBar.View.FindViewById<TextView>(Resource.Id.snackbar_text); txtMessage.SetTextColor(Android.Graphics.Color.Red); txtMessage.SetTextSize(Android.Util.ComplexUnitType.Dip, 12); //Show the snackbar snackBar.Show(); };

      • -And there you go, a custom SnackBar Smile
      • image

      If you’re wondering why you need to pass a reference to a view (Button in our case) as SnackBar first parameter is because internally it walks up the visual tree so that can properly position itself at bottom position.

       

      Using Xamarin Forms Effects

      $
      0
      0

      Version 2.1 of Xamarin Forms introduced Effects, a nice alternative to custom renderers when all you need is to tweak some properties of the platform native control, they should be seen as an alternative to a custom renderer not as a substitute.

      Let’s quickly see how they work, let’s suppose we want to limit the amount of text that a user can type inside an entry, something that’s not natively possible with Xamarin Forms (at the time of this writing…)

      Create a new Xamarin Forms project and upgrade Xamarin.Forms assemblies to latest stable version greater than 2.1 , in my case is 2.1.0.6529

      image

      Effects are a mix of platform specific code and code that resides in application PCL library, let’s start with the PCL and create a class that uses RoutingEffect  as base class:

      public class MyEntryEffect : RoutingEffect { public MyEntryEffect() : base("MyCompanyName.EntryEffect") { } public int MaxLength { get; set; } }

      As you can see the constructor of this class invokes base constructor passing the fully qualified name of the platform specific effect to be created (“MyCompanyName.EntryEffect” more details on this soon)

      It’s time to apply our Effect (or as I prefer ‘extension’) to a Xamain Forms Entry, in my project I’ve added a MainView.xaml page and this is related XAML.

      <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:demoEffects2="clr-namespace:DemoEffects2;assembly=DemoEffects2" x:Class="DemoEffects2.MainView"> <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"> <Entry Placeholder="Try to type more than 5 chars.." > <Entry.Effects> <demoEffects2:MyEntryEffect MaxLength="5" /> </Entry.Effects> </Entry> </StackLayout> </ContentPage>

      Quite easy to understand: We added our custom MyEntryEffect effect to Entry’s Effects collection and set it’s MaxLength property to 5.

      Is now time to switch to platform specific projects and implement the code that reads the value of MaxLength property and applies this limit to platform specific control.

      Let’s start with Android:

      [assembly: ResolutionGroupName("MyCompanyName")] //Note: only one in a project please... [assembly: ExportEffect(typeof(EntryEffect), "EntryEffect")] namespace DemoEffects2.Droid { public class EntryEffect : PlatformEffect { protected override void OnAttached() { try { //We get the effect matching required type, we might have more than one defined on the same entry var pclEffect = (DemoEffects2.MyEntryEffect)this.Element.Effects.FirstOrDefault(e => e is DemoEffects2.MyEntryEffect); TextView editEntry = this.Control as TextView; editEntry?.SetFilters(new Android.Text.IInputFilter[] { new Android.Text.InputFilterLengthFilter(pclEffect.MaxLength) }); } catch (Exception ex) { //Catch any exception } } protected override void OnDetached() { } protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) { base.OnElementPropertyChanged(args); try { if (args.PropertyName == "Your property name") { //Update control here... } } catch (Exception ex) { Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); } } } }

      Inside the Android project I have created an EntryEffect class that inherits from PlatformEffect and implemented two familiar overrides: OnAttached and OnDetached.

      As you might expect the first is invoked when Effect is applied to the control and can be used to initialize the property of Android’s native control while OnDetached is called when the effect is removed and can be used to perform any cleanup. 

      From inside this methods we have access to three fundamental properties:

      Container: The platform specific control used to implement the layout.

          • Control: The platform specific counterpart of Xamarin Forms control.

      Element: The Xamarin Forms control being rendered.

      Since Effect can be added to Effects collection of any control the code must take this into consideration and degrade gracefully in case actions cannot be completed due to a control type mismatch.

      Inside OnAttached we retrieve the PCL effect so that we can read it’s MaxLenght property and we cast the Control property to a TextView, if casting fails we simply do nothing otherwise we add a filter that limits the number of typed chars inside the TextView.

      Even if not used in this sample, the code includes OnElementPropertyChanged override that can be used when you want to be notified when a property of the control changes (e.g. IsFocused) and do something when this happens.

      Last, but absolutely not least come the two attributes ResolutionGroupName and ExportEffect

      ResolutionGroupName : Allows you to define a custom namespace for you effects to prevent naming collision, it must be used once in the platform specific project.

      ExportEffect: Is the name that’s used by initial effects discovery process and it accepts the type of the effect it is applied to and the name you want to export for discovery.

      The concatenation of ResolutionGroupName and ExportEffect id is used by RoutingEffect class (see it’s base constructor in preceding code) for proper identification.

      As for custom renderers is not necessary to implement the effect for each class, if undefined it simply gets ignored.

      Here’s the iOS effect version:

      [assembly: ResolutionGroupName("MyCompanyName")] //Note: only one in a project please... [assembly: ExportEffect(typeof(EntryEffect), "EntryEffect")] namespace DemoEffects2.iOS { public class EntryEffect : PlatformEffect { protected override void OnAttached() { try { //We get the effect matching required type, we might have more than one defined on the same entry var pclEffect = (DemoEffects2.MyEntryEffect)this.Element.Effects.FirstOrDefault(e => e is DemoEffects2.MyEntryEffect); UITextField editEntry = this.Control as UITextField; if (editEntry != null) { editEntry.ShouldChangeCharacters = (UITextField textField, NSRange range, string replacementString) => { // Calculate new length var length = textField.Text.Length - range.Length + replacementString.Length; return length <= pclEffect.MaxLength; }; } } catch (Exception ex) { //Catch any exception } } protected override void OnDetached() { } } }

      Simpler, but more flexible, Xamain Forms effects represent a valid alternative to Renderers, I’m pretty sure that we’ll see many open source effects coming from th Xamarin community.

      If you want to know more about Effects, this is the link to follow.

      Happy Effecting.


      Xamarin Forms: CarouselView in action

      $
      0
      0

      Xamarin Forms are getting better with each new release, version 2.2, actually in preview, includes new interesting addition like Effects and CarouselView.

      CarouselView replaces the now deprecated CarouselPage with a more flexible control that can be embedded in any page and can have any size you want, being curious I wanted to see it in action.

      I created a new Xamarin Forms project and updated all projects NuGet Packages to version 2.2.0.5-pre2 (you have to select “Include prerelease” option to have it listed since, at the moment, it hasn’t officially released yet.

      image

      I suddenly added a MainView xaml page to the PCL project and set it as MainPage inside App.cs

      public class App : Application { public App() { // The root page of your application MainPage = new MainView(); } }

      CarouselView inherits from ItemView so it requires a collection of items associated to it’s ItemSource property, I then created an array of Persons and associated to CarouselView with this code

      public partial class MainView : ContentPage { public MainView() { this.InitializeComponent(); Person[] persons = { new Person() { Name = "Corrado", ImageUri = "male.png" }, new Person() { Name = "Giulia", ImageUri = "female.png" } }; this.MyCarouselView.ItemsSource = persons; CarouselView v; } } public class Person { public string Name { get; set; } public string ImageUri { get; set; } }

      MyCarouselView is the CarouselView I previously added to MainView.xaml:

      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:testCarouselView="clr-namespace:TestCarouselView;assembly=TestCarouselView" x:Class="TestCarouselView.MainView"> <CarouselView x:Name="MyCarouselView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" /> </ContentPage>

      Great, but we’re missing something: The ItemTemplate. but since I want to use a different template for each page I decided to use another recent addition to Xamarin Forms: the DataTemplateSelector, so I created this class that inherits from abstract DataTemplateSelector.

      public class CarouselTemplateSelector : DataTemplateSelector { public DataTemplate MaleTemplate { get; set; } public DataTemplate FemaleTemplate { get; set; } protected override DataTemplate OnSelectTemplate(object item, BindableObject container) { Person person = (Person)item; switch (person.ImageUri) { case "male.png": return MaleTemplate; case "female.png": return FemaleTemplate; default: throw new ArgumentOutOfRangeException(); } } }

      So simple that don’t think it requires a detailed explanation, it just returns proper DataTemplate depending on the name of ImageUri, ok, not very professional but this is just a demo right? Smile

      I generally like to have TemplateSelectors instantiated via xaml together with their associated template definition in one place, so I added them to MainView xaml resources, here’s complete markup:

      <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:testCarouselView="clr-namespace:TestCarouselView;assembly=TestCarouselView" x:Class="TestCarouselView.MainView"> <ContentPage.Resources> <ResourceDictionary> <!--Female template--> <DataTemplate x:Key="FeMaleTemplate"> <StackLayout BackgroundColor="Pink" Orientation="Horizontal"> <Image Source="{Binding ImageUri}" VerticalOptions="Center" Margin="50,0,0,0" WidthRequest="100" HeightRequest="200" /> <Label VerticalOptions="Center" Margin="60,0,0,0" Text="{Binding Name}" TextColor="Black" FontSize="30" /> </StackLayout> </DataTemplate> <!--Male template--> <DataTemplate x:Key="MaleTemplate"> <Grid BackgroundColor="Aqua"> <Image Source="{Binding ImageUri}" VerticalOptions="Start" Margin="00,50,0,0" WidthRequest="100" HeightRequest="200" /> <Label VerticalOptions="Center" HorizontalOptions="Center" Margin="0,500,0,0" Text="{Binding Name}" TextColor="Black" FontSize="30" /> </Grid> </DataTemplate> <!--Template selector--> <testCarouselView:CarouselTemplateSelector x:Key="CarouselTemplateSelector" MaleTemplate="{StaticResource MaleTemplate}" FemaleTemplate="{StaticResource FeMaleTemplate}" /> </ResourceDictionary> </ContentPage.Resources> <!--Carousel View--> <CarouselView PositionSelected="OnPositionSelected" x:Name="MyCarouselView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemTemplate="{StaticResource CarouselTemplateSelector}" /> </ContentPage>

      From the xaml you’ll immediately recognize the two (simple) DataTemplates, the custom DataTemplateSelector , how it gets associated to CarouselView ItemTemplate but if you look closely you’ll also recognize a nice addition to Forms v2.2: Margin property!

      Yes we can now stop using nested views with Padding to fine tune control position inside a Page, well done Xamarin!

      If you want to be informed when the position of CarouselView changes just subscribe PositionChanged event, in my case I mapped it to this method:

      private void OnPositionSelected(object sender, SelectedPositionChangedEventArgs e) { Debug.WriteLine(e.SelectedPosition.ToString()); }

      We can now run the sample code and we’ll get this outputs (Android/iOS)

      Android       ios

      CarouselView is a great new entry, in special case if you want to create applications based on sliding views (quite common today) there’s just one feature I miss: Orientation, at the moment looks like you can only slide horizontally, hope Xamarin will consider it for final release.

      AutoHide FloatingActionButton in Xamarin.Android

      $
      0
      0

      My main phone is an Android and as a news app I use a 3rd party aggregator that, al nearly all Android apps today is based on Material Design.
      Using it everyday I couldn’t ignore a nice UI feature it exposes: it’s share button (a Material Design’s FloatinActionButton) fades out when you scroll the list vertically and it reappears when you scroll the list down.
      Being curious, I wanted to know how to create that effect using Xamarin.Android.

      This is my final result:

      hidefab

      Since there’s a lot of setup involved I won’t go too much into code detail and setup, you can grab the project source code from here https://github.com/corradocavalli/Xamarin.Android.HideMyFAB

      I’m assuming you have some basic knowledge of Material Design and  related steps to enable it into a Xamarin.Android app so and I’ll go straight to the point: The view you see is made up of a CoordinatorLayout that hosts a NestedScrollView that contains a series of CardViews and in the bottom right corner there is our FloatingActionButton.

      The trick of making it disappear is to add a custom behavior so that CoordinatorLayout knows that it has to invoke a behavior that takes care to hide/show it when something happen, in our case when user scrolls up or down.

      This is the required behavior

      Inside OnNestedStartScroll we inform the CoordinatorLayout that we want to receive scroll events when user scrolls vertically while inside OnNestedScroll we receive a reference to the FloatingActionButton (since we have applied the behavior to it) and depending on scroll direction we show/hide it.

      The hard part of migrating this code to Xamarin was fixing the weird compilation issues I was having, I thank community guy fex for giving me the hint to add the [Register] attribute at the top to the class definition and inheriting from CoordinatorLayout instead of my initial FloatingAction. No idea if this is a bug, I’ve seen someone already filed it on Bugzilla but still without any reply.

      Is now time to associate out behavior to the FloatinActionButton, I’ll do that using the standard approach to define the fully qualified path to the class inside strings.xml for better refactoring.

      and now it’s just a matter of attach it to the button

      If you use material design in your appls you’ll immediately recognize the now stanrdard elements, the only real new is the layout_behavior attribute applied to the FloatingActionButton that points to our custom behavior.

      There are indeed simpler alternatives like James Montemagno component available here but looks like it is now deprecated and I think that, once you know how to fix the ACW compilation issues, knowing how to use material design behaviors wont hurt.

      Enjoy Smile

      A Smart RecyclerView Adapter for Xamarin.Android

      $
      0
      0

      RecyclerView is the recommended way to represents a collection of items in Android applications, the good and old ListView is now deprecated since RecyclerView offers a lot of improvements like flexible layout, item recyclying and enforces the ViewHolder pattern.

      If you’re new to RecyclerView in Xamarin Android I recommend this article from Xamarin site, since it is also the origin project I’ve used on this post and this is not a RecyclerView tutorial.
      This post originates since every time I need to use a RecyclerView, even for simple demos like this blog post, I end up rewriting the same boilerplate code, so I decided to create a simple generic adapter that simplifies things for me.

      Source code and demo is available on GitHub here, so get it and have a look if you want to know more about the internals, I’ll just show you how to use it updaing the original Xamarin demo.

      Just create a class that inherits from abstract SmartRecyclerAdapter<T> class

      as you see, you just have to implement two methods OnLookupViewItems and OnUpdateView: OnLookupViewItems is used to extract the view items from inflated layout and save them into provided generic viewholder
      OnUpdateView is used to update the same view items with the fresh values coming from provided Item.

      Let’s see now in action, exploring the code in MainActivity:

      Very simple: I created an instance of the PhotoRecyclerAdapter passing to its constructor: the RecyclerView, an ObservableCollection<T> as item source and the optional id of the layout to inflate to create the items views (more on this later)

      Since we’re using an ObservableCollection<T> the list is smart enough to automatically invoke the several NotifyXYZ methods when you add/remove/move items from the collection as when the “Clear+Add” button of the demo is clicked.

      What if you need to use different layouts depending on items properties? just override base class GetViewIdForType method and return an int that will be passed to the othere method you’ll have to override named OnGetViewId inside this method, depending on passed viewTypeId you’ll return the item id to inflate for such element.

      The adapter automatically raises an ItemSelected event when an item is clicked, passing null as RecyclerView parameter on PhotoRecyclerAdapter constructor, disables this behavior and you can implement your own item selection strategy.

      It’s just a starting point, hope you’ll like it. Smile

      I am a Xamarin MVP!

      $
      0
      0

      Xamarin, like Microsoft has its own MVP (Most Valuable Professional) program that awards people “who have demonstrated an exemplary commitment to helping others get the most out of their experience with Xamarin by sharing their passion, real-world knowledge, and technical expertise with developers all over the world.”

      I am pleased to announce that I’ve been awarded Xamarin MVP, and this makes me extremely proud and happy, being the first Italian in this close group of internationally known Xamarin experts, give me a high level of responsibility and I’ll do my best continuing sharing my technology passion.

      If you haven’t tried Xamarin yet, I encourage you to do it, a lot changed since 2014 when I started approaching it (no Forms yet…) it is now a mature product and if you’re eager to learn more Xamarin University is here to help.

      Thanks Xamarin!

      Joining IBV

      $
      0
      0

      image

      Effective June 1st, after nearly 14 years as independent consultant I’ve joined the Swiss based company IBV as Senior Software Development Engineer, decision comes from the great work and career opportunity the company offered me just at a time when I was felting the need for new working stimuli.

      How this is going to change my life? not much indeed I’ll probably have to visit Switzerland more often and enjoy beautiful landscapes like this while driving to work

      image 

      and focus more on Natural User Experience (like Surface Hub and Hololens)

      image image

      The initial days I’ve spent in the near Zurich based office were really enjoyable, I’ve smelt the typical ‘startup’ like energy even if the company is now 35 years old.

      Another unexpected surprise was to discover that one of my new colleagues was my good old friend Alessandro Teglia who also joined as Chief Digital Officer.

      It was when the company’s boss, just after signing the contract, gave me this talisman, that I realized I did one of the best decision in my life and I thank fate for this.

      image

      Last but not least, my “boss” (well, sound strange for me to call it “my boss” Smile) Gian Paolo Santopaolo, who is not only a great professional (and MVP like me) but also very great cook, he can do little food masterpieces in minutes.

      Regarding my community commitments, nothing changes, I’ll try to blog more about my new job (BTW: follow our company twitter account https://twitter.com/IbvSolutions) and, as usual, I’ll spread my technology passion as I always did in the past.

      I wish you all to work in a lovely place as IBV, it’s just there and fate will certainly let you find it, just don’t give up searching.

      image

      Viewing all 46 articles
      Browse latest View live




      Latest Images