Corrado's Blog 2.0

Online thoughts of a technology funatic

Xamarin.Forms.Behaviors v.1.1.0

I’ve pushed an update to Xamarin.Forms.Behaviors library, fixed some bugs and added Relative Commanding to EventToCommand Behavior.

What is Relative Commanding?

It is a way to let EventToCommand invoke a Command that is exposed by a ViewModel that’s not part of actual BindingContext, typical example is when you are inside an ItemTemplate (ViewCell in Xamarin Forms) and you need to invoke a command that’s hosted inside another viewmodel.

To support this feature I’ve added two new properties to EventToCommand: CommandName and CommandContext, former is the name (string) of the Command you want to invoke, latter is the BindingContext that exposes that command.

How can you link CommandContext with desired BindingContext? Use the new RelativeContext markup extension exposed by Behaviors library to ‘link’ a BindingContext to another (CommandContext in case of EventToCommand)

Here’s a sample taken from GitHub repo.

MainViewModel exposes both an ObservableCollection of Items and a NickSelectedCommand and is also bound to MainPage’s BindingContext, here’s how you can let ListView’s items invoke MainViewModel command.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"
        x:Class="Xamarin.Behaviors.Demo.Views.MainView"
      x:Name="MainPage"> 

  <ListView ItemsSource="{Binding Items}"
      IsGroupingEnabled="false"
      RowHeight="60">
   <ListView.ItemTemplate>
    <DataTemplate>
     <ViewCell>
      <StackLayout Orientation="Horizontal" Padding="10" >
       <StackLayout Orientation="Vertical"  HorizontalOptions="FillAndExpand" Spacing="-50"  >
        <Button Text="{Binding NickName}">
         <b:Interaction.Behaviors>
          <b:BehaviorCollection>
           <b:EventToCommand CommandNameContext="{b:RelativeContext MainPage}"
                 EventName="Clicked"
                 CommandName="NickSelectedCommand"
                 CommandParameter="{Binding NickName}" />
          </b:BehaviorCollection>
         </b:Interaction.Behaviors>
        </Button>
        
       </StackLayout>
      </StackLayout>

     </ViewCell>
    </DataTemplate>
   </ListView.ItemTemplate>
  </ListView>
  
  
 </StackLayout>
</ContentPage>

As you see we ‘linked’ CommandNameContext to the BindingContext associated to MainPage element through RelativeContext extension an we told EventToCommand that button’s Clicked event should invoke a Command named “NickSelectedCommad” also note that original BindingContext is preserved so we can safely use binding for the CommandParameter property.

Happy Behavioring… Smile

Application wide resources in Xamarin Forms

Xamarin Form’s XAML infrastructure is very similar to Windows counterpart (and I thank Xamarin for that!) unfortunately in current version a feature is not there yet: Application wide resources that is resources  that are shared among all application pages.

In this blog post I’ll show you how to add this feature to a Xamarin Forms application.

Step 1

Create a new Xamarin Forms application (shared)

image

Step 2

Create a CoreApplication class that inherits from View, this class provides a ResourceDictionary property and can be lately extended with other Application features.

namespace Xamarin.Forms
{
 public class CoreApplication:View
 {
 }
}

Step 3

Create an App class that inherits for CoreApplication that is splitted between XAML and associated code-behind.

<?xml version="1.0" encoding="utf-8" ?>
<CoreApplication xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="SharedResources.App">
 <CoreApplication.Resources>
  <ResourceDictionary>
   ... app wide resources here...
  </ResourceDictionary>
 </CoreApplication.Resources> 
</CoreApplication>

code behind:

namespace SharedResources
{
 public partial class App : CoreApplication
 {
  static App current;

  public App()
  {
   InitializeComponent();
  }

  public static App Current
  {
   get
   {
    return current ?? (current = new App());
   }
  }

  public Page GetMainPage()
  {
   return new MainView();   
  }
 }
}

As you see, together with standard XAML initialization call InitializeComponent the call exposes a Current static application returning a singleton App instance and Xamarin Forms standard method GetMainPage that returns application’s main page.

Step 4

Since App class has changed we need to update the code generated by Xamarin Forms template that retrieve application’s main page in each platform, thank to Current property modification is very easy, just a line of code for each supported platform.

Android

namespace SharedResourced.Droid
{
 [Activity(Label = "SharedResourced", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
 public class MainActivity : AndroidActivity
 {
  protected override void OnCreate(Bundle bundle)
  {
   base.OnCreate(bundle);

   Xamarin.Forms.Forms.Init(this, bundle);

   SetPage(SharedResources.App.Current.GetMainPage());
  }
 }
}

iOS

namespace SharedResourced.iOS
{
 [Register("AppDelegate")]
 public partial class AppDelegate : UIApplicationDelegate
 {
  UIWindow window;

  public override bool FinishedLaunching(UIApplication app, NSDictionary options)
  {
   Forms.Init();

   window = new UIWindow(UIScreen.MainScreen.Bounds);

   window.RootViewController = SharedResources.App.Current.GetMainPage().CreateViewController();

   window.MakeKeyAndVisible();

   return true;
  }
 }
}

Windows Phone

namespace SharedResourced.WinPhone
{
 public partial class MainPage : PhoneApplicationPage
 {
  public MainPage()
  {
   InitializeComponent();

   Forms.Init();
   Content = SharedResources.App.Current.GetMainPage().ConvertPageToUIElement(this);
  }
 }
}

Step 6

Since we need to lookup application wide resources in XAML, let’s use one of the less known XAML features: Custom Markup Extension. As in Windows, defining a Custom Markup Extension in Xamarin Forms is just a matter of implementing the IMarkupExtension interface (not sure about requirement of class name ending with *Extension but I’ll follow the convention)

Here’s the code

namespace Extensions
{
 [ContentProperty("Key")]
 public class GlobalResourceExtension : IMarkupExtension
 {
  public string Key { get; set; }
  public object ProvideValue(IServiceProvider serviceProvider)
  {
   if (this.Key == null)
    throw new InvalidOperationException("you must specify a key in {GlobalResource}");
   if (serviceProvider == null)
    throw new ArgumentNullException("serviceProvider");

   object value;
   bool found = App.Current.Resources.TryGetValue(this.Key, out value);
   if (found) return value;
   throw new ArgumentNullException(string.Format("Can't find a global resource for key {0}", this.Key));
  }
 }
}

No rocket science, just a simple lookup into Application’s resource dictionary to get required resource.

Step 7

Time to test our work, let’s add some dummy resources to App.Xaml and consume them in a XAML page.

<CoreApplication xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="SharedResources.App">
 <CoreApplication.Resources>
  <ResourceDictionary>
   <LayoutOptions x:Key="hOptions" Alignment="Start" />
   <x:String x:Key="color">Red</x:String>
   <x:String x:Key="color2">#CC00FF00</x:String>
   <OnPlatform x:Key="Angle" x:TypeArguments="x:Double">
    <OnPlatform.iOS>0</OnPlatform.iOS>
    <OnPlatform.Android>-15</OnPlatform.Android>
    <OnPlatform.WinPhone>90</OnPlatform.WinPhone>
   </OnPlatform>
  </ResourceDictionary>
 </CoreApplication.Resources>
</CoreApplication>

MainView.Xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:e="clr-namespace:Extensions;assembly=SharedResourced"
        x:Class="SharedResourced.MainView">
 <StackLayout Spacing="30">
  <Label Text="Hello" 
     VerticalOptions="{e:GlobalResource hOptions}" 
     TextColor="{e:GlobalResource color2}" 
     HorizontalOptions="Center" />

  <Label Text="Hello2" 
     VerticalOptions="{e:GlobalResource hOptions}" 
     Font="Large" 
     TextColor="{e:GlobalResource color}" 
     HorizontalOptions="Center"
     Rotation="{e:GlobalResource Angle}"/>
 </StackLayout>
</ContentPage>

Note the presence of xaml namespace “e” that contains our custom markup extension.

Here you go, just a few steps and now you have Application wide resources instead of repeating them in each page.

Here’s the Windows Phone and Android output (sorry no Mac machine connected at this moment Winking smile)

image  image

Introducing Xamarin Forms Behaviors

The goal of this post is to introduce you to the Xamarin.Forms.Behavior package available on NuGet, if you landed here I presume you already know what Xamarin Forms is, if not, follow this link so you’ll understand why so many developers are excited about it.

Now that I can assume you’re a Xamarin Forms master, let’s concentrate on Behaviors. Once I read Xamarin Forms documentation I was really happy to see that you can design cross-platforms user interfaces using XAML and that the XAML support in Xamarin Forms is nearly identical to the one available in Windows development apart some minor differences.

If you don’t know what a Behavior is I can summarize it for you in this sentence: The capabity to add code inside a UI described using XAML” the question now is: Why should I add code inside XAML, hasn’t code behind created just for this? well, yes and no, if you know MVVM (if not, you should!) you’ll know that the entire logic should reside inside the VieModel associated with the View and that communication between View and ViewModel should happen (in a perfect world) through Databinding.

Unfortunately in “real” world this is not always possible and you have to use code to make things work, often this code resides in code behind and for this reason is not testable and not even reusable.

Let’s take an example: A simple view made up of two Entry elements and a Button, the View has a ViewModel associated to its BindingContext and we want the button to be enabled only when both Entry fields are not empty and it’s enabled state must toggle “live” while user typing.

This is the XAML contained inside Xamarin Forms’s PCL project:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"      
        x:Class="Xamarin.Behaviors.Demo.Views.MainView">
 <StackLayout>
  <Entry Placeholder="Enter Firstname" />
  <Entry  Placeholder="Enter Lastname" />
  <Button Text="Ok" Command="{Binding TestCommand}" />    
 </StackLayout>
</ContentPage>

and here’s the ViewModel:

public class MainViewModel : INotifyPropertyChanged
 {
  public event PropertyChangedEventHandler PropertyChanged;

  private string firstName = "Nome";
  private string lastName = "Cognome";
  private Command testCommand;
  private Command<object> unfocusedCommand;
  private string message;
  private string welcomeMessage; 
  
  public string FirstName
  {
   get { return this.firstName; }

   set
   {
    if (value != this.firstName)
    {
     this.firstName = value;
     this.RaisePropertyChanged();
     this.TestCommand.ChangeCanExecute();
    }
   }
  }
  
  public string LastName
  {
   get { return this.lastName; }

   set
   {
    if (value != this.lastName)
    {
     this.lastName = value;
     this.RaisePropertyChanged();
     this.TestCommand.ChangeCanExecute();
    }
   }
  }
  
  public string Message
  {
   get  {return this.message; }

   private set
   {
    if (value != this.message)
    {
     this.message = value;
     this.RaisePropertyChanged();
    }
   }
  }  
  public string WelcomeMessage
  {
   get { return this.welcomeMessage;}

   set
   {
    if (value != this.welcomeMessage)
    {
     this.welcomeMessage = value;
     this.RaisePropertyChanged();
    }
   }
  }
  
  public Command TestCommand
  {
   get
   {
    return this.testCommand ?? (this.testCommand = new Command(
      () =>
      {
       this.WelcomeMessage = string.Format("Hello {0} {1}", this.FirstName, this.LastName);
      },
      () =>
      {
       return !string.IsNullOrEmpty(this.FirstName) && !string.IsNullOrEmpty(this.LastName);
      }));
   }
  }

  public Command<object> UnfocusedCommand
  {
   get
   {
    return this.unfocusedCommand ?? (this.unfocusedCommand = new Command<object>(
      (param) =>
      {
       this.Message = string.Format("Unfocused raised with param {0}", param);
      },
      (param) =>
      {
       // CanExecute delegate
       return true;
      }));
   }
  }
  
  protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  {
   PropertyChangedEventHandler handler = PropertyChanged;
   if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  }
 }

ViewModel is associated with the View’s constructor for brevity:

public partial class MainView
 {
  public MainView()
  {
   InitializeComponent();
   this.BindingContext = new MainViewModel();
  }
 }

As you see the Button is connected to ViewModel’s TestCommand via Databinding and thanks to ICommand interface it is enabled only when both ViewModel’s FirstName and LastName properties are not empty.

Now the hardest part: How do we update those properties when Entry content changes?

Easy: we subscribe Entry’s TextChanged method and when it fires we update associated property. Cool, but wouldn’t it be nice if we could encapsulate this logic into a reusable component, usable in XAML, so that we don’t need to reinvent the wheel each time?

Here’s where Behaviors can help you.

Install Xamarin.Forms.Behaviors Package from NuGet and  and create a class that inherits from Behavior<T> where <T> is the UI component that the behavior will attach to, in our case the Entry element.

public class TextChangedBehavior : Behavior<Entry>
 {
  public static readonly BindableProperty TextProperty = BindableProperty.Create<TextChangedBehavior, string>(p => p.Text, null, propertyChanged: OnTextChanged);

  private static void OnTextChanged(BindableObject bindable, string oldvalue, string newvalue)
  {
   (bindable as TextChangedBehavior).AssociatedObject.Text = newvalue;
  }

  public string Text
  {
   get { return (string)GetValue(TextProperty); }
   set { SetValue(TextProperty, value); }
  }

  protected override void OnAttach()
  {
   this.AssociatedObject.TextChanged += this.OnTextChanged;
  }

  private void OnTextChanged(object sender, TextChangedEventArgs e)
  {
   this.Text = e.NewTextValue;
  }

  protected override void OnDetach()
  {
   this.AssociatedObject.TextChanged -= this.OnTextChanged;
  }
 }

Behavior and Behavior<T> both have OnAttach and OnDetach methods that gets invoked when the behavior is attached/detached from parent UI element, so we subscribe TextChanged event and when it triggers we update behavior’s bindable property Text.

I’ll be you’re now wondering: How do I use it in my XAML? very easy, here’s the updated XAML for Entry element (just first one indicated for brevity)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"
        x:Class="Xamarin.Behaviors.Demo.Views.MainView">
 <StackLayout>
  <Entry Placeholder="Enter Firstname" >
   <b:Interaction.Behaviors>
    <b:BehaviorCollection>
     <b:TextChangedBehavior Text="{Binding FirstName, Mode=TwoWay}" />     
    </b:BehaviorCollection>
   </b:Interaction.Behaviors>
  </Entry>
  ...
  </StackLayout>
</ContentPage
  

After adding a xmlns pointing to Xamarin.Forms.Behavior namespace we “inject” the code into XAML, so now as we type on Entry the Firstname property it’s updated (and vice versa of course thanks to INotifyPropertyChanged and Two Way binding mode.)

One of the real advantages of using Behaviors in Windows Development is that they’re visually supported by Expression Blend design tool, so you don’t even need to write any XAML, just drag the behavior and configure it using point and click Smile unfortunately since we don’t even have a XAML designer in Xamarin Forms typing is the only available solution at the moment.

If you think the syntax is quite boring I agree, that’s why inside the project on GitHub I added a XML snippet that generates the surrounding code for you, just grab it and import it in Visual Studio, add the behavior syntax and press Ctrl+K+S

image

and you’ll have the plumbing code added for you, don’t forget to add required xmlns directive/s.

xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"

since it’s not added automatically by the snippet.

Am not a Xamarin Studio expert so I don’t know if it support XML Expansions, if so send me the snippet and I’ll add it to the project.

Here’s the XAML taken from the example available on GitHub:

<Entry Placeholder="Enter Firstname" >
   <b:Interaction.Behaviors>
    <b:BehaviorCollection>
     <b:TextChangedBehavior Text="{Binding FirstName, Mode=TwoWay}" />
     <b:EventToCommand EventName="Unfocused" Command="{Binding UnfocusedCommand}" CommandParameter="FirstName" />
    </b:BehaviorCollection>
   </b:Interaction.Behaviors>
  </Entry>

the example shows two behaviors included in the package, TextChangedBehavior and EventToCommand, a behavior that invokes a Command when an event occurs.

Congratulations! you’re now able to write your own behavior, group them in a portable library and reuse it in every Xamarin Forms project.

If you’re already a XAML developer you already know what behaviors are and I hope you’ll like to have them in Xamarin Forms, if not I encourage you to play with it, personally can’t even think using XAML with MVVM without them.

Ok, now let’s dream about a Xamarin Forms designer supporting the same Behavior infrastructure as Expression Blend, am I asking too much? we’ll see.

Cheers!

NuGet Package: here

GitHub repo: here

Add “intellisense” to Xamarin .axml files

When you manually edit .axml files inside Visual Studio 2013 you don’t have any minimal intellisense support, and, as Visual Studio user, you know how frustrating is typing without any kind of help.

image

Since editing the same file using the XML editors brings you a ‘partial’ intellisense i tried to find what was the difference and finally found how to enable it also inside Android designer source view.

  1. 1-With Designer in source view, select Visual Studio’s xml menu and then Schemas…
  2. image
  3. 2-Navigate to C:\Program Files (x86)\MSBuild\Xamarin\Android and select android-layout-xml.xsd file.
  4. 3-Click Ok to confirm and dismiss the dialog.
  5. Here’s what you now get when typing android: in source view:
  6. image
  7. Of course, this is not the same experience we have in XAML, but better than nothing.
  8. After adding the schema, the first time you add a new Android layout Visual Studio asks you to trust a new file, just select Trust and everything will work as usual in future.
  9. Enjoy!

Scroll with snapping in Windows Phone 8

I’m working on a Windows Phone 8 app that has an “unconventional” UI as it does not follow Windows Phone UX guidelines (it’s a company private app) and so it has home page made up of several screens horizontally aligned that user can pan.

Untitled

I started wrapping the screens inside a horizontally oriented WrapPanel and content, as expected, scrolled.
Mission accomplished? well not really: Content was scrolling but final experience was poor because of missing snapping feature, it was extremely easy lo leave home page with more than one screen visible.

image

To overcome this issue I decides to create a Blend Behavior that attached to a ScrollViewer would take care of smoothly bring into view the correct screen depending on scroll direction.
Solution wasn’t as immediate as previous one since I decided to use an ItemsControl as ScrollViewer’s content since I have the same requirements in other views where content is databound and I had to “dig into” ScrollViewer and attach to both horizontal and vertical scrollbars (yes, I need to support both scrolling direction) but at the end it worked.

Yeah! but, there’s another UX issue: ScrollViewer has the ‘compression’ feature, the one often used to create the famous “Pull to refresh” functionality in lists. Since final experience was not acceptable and since I haven’t found a reliable way of disabling it I abandoned this 2nd solution and decided to go handling all scrolling details.

Enter the SnappingScrollViewer

I won’t bother you with a long code listing (you can get the source code here) but what I did basically was:

  1. -Create a class that inherits from Canvas
  2. -Register Canvas Manipulation events
  3. -Use ManipulationMode.Delta event to set Canvas left/top offset to scroll content
  4. -Use ManipulationMode.Completed event to detect current scrolling position and scroll the screen to proper position using an animation.

Since animation target requires a dependency property and my class is based on Canvas SetLeft/SetTop method I used an old XAML trick adding a custom ScrollOffset dependency property and invoking proper method inside property’s changed event:

protected virtual void OnScrollOffsetChanged(double oldValue, double newValue)
        {
            if (this.IsVertical)
            {
                SetTop(this.content, newValue);
            }
            else
            {
                SetLeft(this.content, newValue);
            }
        }

content is ScrollViewer’s ItemsControl that I get into Loaded event.

private void OnLoaded(object sender, RoutedEventArgs e)
        {
            this.content = (ItemsControl)this.Children.First();
            this.totalPages = (int)(this.IsVertical ? (this.content.ActualHeight / this.ItemSize) : (this.content.ActualWidth / this.ItemSize));
            this.snapAmount = this.ItemSize * this.Inertia;
            this.itemIndex = this.InitialIndex;
            if (this.IsVertical)
            {
                SetTop(this.content, -this.InitialIndex * this.ItemSize);
            }
            else
            {
                SetLeft(this.content, -this.InitialIndex * this.ItemSize);
            }
        }

Use is very simple:

<smoothScroller:SnappingScrollViewer x:Name="LayoutRoot"
                                   ItemSize="480"
                                   InitialIndex="2"
                                   IsVertical="False"
                                   Background="White">
        <ItemsControl Background="#FFE01818">
            <ListBoxItem>
                <Grid Background="Aqua"
                      Width="480"
                      Height="800" />
            </ListBoxItem>
            <ListBoxItem>
                <Grid Background="YellowGreen"
                      Width="480"
                      Height="800" />
            </ListBoxItem>

            <ListBoxItem>
                <Grid Background="Orange"
                      Width="480"
                      Height="800" />
            </ListBoxItem>
            <ListBoxItem>
                <Grid Background="Red"
                      Width="480"
                      Height="800" />
            </ListBoxItem>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </smoothScroller:SnappingScrollViewer>

Limitations in sample code: All content must have the same dimension and no support of dynamically added items (did that in production code but wanted to keep demo simple Smile)

Go grab the code and enhance it depending on your needs.

Note for Windows Phone 8.1: ScrollViewer in Windows Phone 8.1 has a HorizontalSnapPointType property that can be used to “snap” content, so this XAML will work as expected

<ScrollViewer HorizontalScrollMode="Enabled"
                      HorizontalScrollBarVisibility="Visible"
                      HorizontalSnapPointsType="Mandatory">
            <StackPanel Orientation="Horizontal">
                <Grid Height="800"
                      Background="#FF1EAA4B"
                      Width="480" />
                <Grid Height="800"
                      Background="#FFDAB611"
                      Width="480" />
                <Grid Height="800"
                      Background="#FF9C0EC5"
                      Width="480" />
            </StackPanel>
        </ScrollViewer>

Unfortunately Compression effect is still present Sad smile if anyone knows how to disable it just let me know, I’m more than interested.

Enjoy!

 

Xamarin: Infinite scrolling list in iOS app

I’ve spend the last few weeks studying Xamarin, not because I’m considering abandoning the Windows platform but because I think it’s clear that, as developer, we need to take note that there are other big platforms with which it is right to live with.

While not yet mature and in some cases quite cumbersome, my experience with it was highly positive and I absolutely recommend it in case you need to create Android and/or iOS applications.

This post comes from a need I had during development of a iOS application: Create an infinite scrolling list of data starting from paged data coming from a REST service.

Note: I’m a Xamarin beginner so this might not be the perfect solution, but it worked fine in my case.

To get infinite scrolling I created a custom UITableSource

public class BookedCarsTableViewSource : UITableViewSource
    {
        private readonly DataService dataService;
        private readonly PagedResult<BookedCarResponse> firstPage;
        private readonly List<BookedCarResponse> bookedCars;
        private int pageIndex;
        private bool isFetching;

        private const string cellId = "bookedCarCell";

        public BookedCarsTableViewSource(DataService dataService, PagedResult<BookedCarResponse> firstPage)
        {
            this.dataService = dataService;
            this.firstPage = firstPage;
            this.bookedCars = firstPage.Result.ToList();
            this.pageIndex = 0;
        }

        public override int RowsInSection(UITableView tableview, int section)
        {
            return (int)Math.Max(this.bookedCars.Count, this.firstPage.TotalCount);
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            int index = indexPath.Row;
            UITableViewCell cell = tableView.DequeueReusableCell(cellId) ?? new UITableViewCell(UITableViewCellStyle.Subtitle, cellId);
            BookedCarResponse bookedCar = this.bookedCars[index];
            cell.TextLabel.Text = bookedCar.CarPlate;
            cell.DetailTextLabel.Text = bookedCar.CompanyName;            
            if (!this.isFetching && this.pageIndex < this.firstPage.TotalPages && index > this.bookedCars.Count * 0.8)
            {
                this.isFetching = true;
                Task.Factory.StartNew(this.LoadMore);
            }

            return cell;
        }

        private async void LoadMore()
        {
            this.pageIndex++;
            var nextPage = await this.dataService.GetBookedCars(this.pageIndex, this.firstPage.PageSize);
            this.bookedCars.AddRange(nextPage.Result);
            this.isFetching = false;
        }
    }

As you see the trick is inside GetCell, when requested index is near the end of currently available items I spin a new request and add results to bookedCars collection.

In order to get initial block of items I used this code inside related controller:

public class BookedCarsScreenController : UITableViewController
    {
        private PagedResult<BookedCarResponse> firstPage;

        public override async void ViewDidLoad()
        {
            base.ViewDidLoad();
            this.firstPage = await DataManager.Current.GetBookedCars(0, 30);
            this.TableView.Source = new BookedCarsTableViewSource(DataManager.Current, firstPage);
            this.TableView.ReloadData();
        }
    }

I had to invoke TableView’s ReloadData otherwise list was appearing initially empty.

Note that since I’m using Subtitle layout I didn’t find the way to use  iOS 6 automatic cell reuse mode.

Hope it helps! Smile

Windows 8: Is app running inside Visual Studio?

Sometimes you need to run some additional debugging code when your app is launched from a development environment (e.g from Visual Studio), of course there are compiler directives for this but I’ve found a property inside WinRT that can make this even easier.

bool isInsideVs = Windows.ApplicationModel.Package.Current.IsDevelopmentMode;

please note that property indicates Development mode, this means that it will probably check whether app is running from \Program Files\WindowsApps folder so if you launch the just compiled app from Start menu on same machine it will still returns true.

Try to sideload the app and in this case it will have the value false.

 

The tale of a GridViewItem customization

Once upon a time, in a galaxy not so far away, there was a guy (me Smile) who was working on a Windows Store 8.1 application and was asked to create a GridView whose items should look like this picture:

image

The guy (again, me) thought: What’s the problem, did it many times! and he started setting a data source:

public class Item
    {
        public string Text { get; set; }
    }

    public class DemoViewModel
    {
        public DemoViewModel()
        {
            this.Items = new List<Item>();
            for (int i = 0; i < 10; i++)
            {
                this.Items.Add(new Item() { Text = "Item " + i });
            }
        }

        public IList<Item> Items { get; set; }
    }

He then added a GridView to a page, bound the data source and created a simple ItemTemplate:

<Page x:Class="GridViewDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:GridViewDemo"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
    <Page.Resources>
        <local:DemoViewModel x:Key="vm"></local:DemoViewModel>
        <DataTemplate x:Key="MyItemTemplate">
            <Grid Width="100"
                  Height="60">
                <TextBlock HorizontalAlignment="Center"
                           TextWrapping="Wrap"
                           Text="{Binding Text}"
                           VerticalAlignment="Center" />
            </Grid>
        </DataTemplate>
        
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          DataContext="{StaticResource vm}">
        <GridView ItemsSource="{Binding Items}"
                  ItemTemplate="{StaticResource MyItemTemplate}"
                   />
    </Grid>
</Page>

Run the solution and he got something quite close to what he was asked to realize:

image

Ok, just a couple of customizations and we’re done, he thought…

Let’s start with the selected background: The guy knows that background brush is managed inside ItemContainerStyle so he fired up Blend 2013, edited GridView’s ItemContainerStyle and here’s what he got:

image

Just a simple GridViewItemPresenter that has a series of Brush properties that give you the opportunity to customize several container aspects

image

In his case he needed to customize the color of SelectedBackground so, since it is bound to a resource named ListViewItemSelectedBackgroundThemeBrush he added a Brush resource with the same name inside Page resources and selected state was done, here’s updated result:

<SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush"
                         Color="Orange"></SolidColorBrush>

image

But a question started to rise in his mind: “How to i set default (gray) background color?” there’s no Background color exposed by GridViewItemPresenter nor he can set it inside ItemTemplate otherwise it wouldn’t change when item is selected.

He tried lookind inside MSDN docs hoping to find a brush key that controls item default background but he had no luck Sad smile and navigated a lot the Internet until he realized he did something similar in the past for a Windows 8.0 application.

He then opened that old source code and discovered what has changed: The GridViewItemPresenter has been introduced in Windows 8.1, here’s how ItemContainerStyle looks in Windows 8.0:

image

Since you have access to all the elements composing the GridViewItem what the guy did was copying the style into Windows 8.1 app and edited VisualStateManager states (I’m sure, dear reader, you know how to do that…)

So, here’s final result:

image

The guy secretly told me that he wasn’t happy for such solution, probably GridViewItemPresenter has been introduced to improve GridView’s performances but he found no other easier way to solve the puzzle.

Based on a true story… Smile

PS: In case you need Windows 8.0 GridView’s ItemContainerStyle you can get it here.

Debug design time issues in Blend 2013

In 2010 (wow! that’s a long time ago…) I blogged about how to debug Blend design time exceptions, since then things have changed, Blend and Visual studio designer merged and so the XAML designer is now hosted in a separate process named XDesProc.exe (at least in Windows Store applications)

Laurent Bugnion has a detailed blog post about how to attach Visual Studio debugger to Blend to debug a Windows Store application at design time so i won’t repeat it here, the reason of this post is to integrate it with another step required when you use Visual Studio 2013 and Blend 2013.

Since with latest release PDB are no longer copied to cache location used by designer your simbols won’t be loaded and your attach procedure won’t work.

The solution is very easy, just point the debugger symbols to the proper PDB files of your application and everything will work as expected.

To point the PDBs just use: Tools –> Options-> Debugger

image

Then add the folder where your app’s PDB file resides.

Acronis True Image 2014 test drive

As a longtime Acronis user it just took me a second to accept the invite to test the 2014 release of True Image backup software.

For those who don’t know it True Image is a backup software solution that you can use to safely backup your files or entire partitions both locally or, with recent releases, also online using Acronis Cloud (5GB included with the product, other plans available)

While Windows includes it’s own backup solution, i can’t even compare it with the flexibility i get from True Image, using incremental backups i can backup my machine in about 5 minutes after initial full backup which takes indeed more than one hour (but i do it about every two months…)

I have lost the count of how many times this software saved my day, last was about two months ago, and each time i do some “risky” installation, a quick backup with True Image is the rule now, consider me “over conservative” but wasting time re-installing stuff because of a failure its something i hate doing and believe me or not, i rarely repave my machine.

About my experience with True Image 2014: I was running 2013 version and I run the setup without removing the previous version, setup properly took care of update without any problem, old backups configuration have been maintained and i backed up my machine in quite about the same “canonical” 5/8 minutes. Just to test compatibility i tried to open previous backups from True Image 2014 and everything went smooth.

Each time i install a new version i always update the USB key i use to boot my machine in case of a full restore, just in case.

Apart some UI changes which tend to keep the program “as easy as possible” relegating advanced features as “options”

image

i haven’t seen big differences compared to 2013 version, probably new features are on Cloud backup that i don’t use due to my poor upload bandwidth that it will take me days to backup and entire partition online.

I’ll keep using version 2014 in forthcoming months as my backup solution and rest assured I’ll keep you informed if something fails (which i really hope won’t happen and I have no reason to think it should indeed…)

Did i ever said that i also clone my machine into VHDs that i can later boot each time i need to install alpha/beta or stuff that will deliberately compromise your Windows installation using Backup Conversion tool? (love it!)

image

If you’re looking for a compete backup solution that’s fast, realiable and (why not?) cheap I always recommend, and I’ll keep recommending, Acronis product. I know that there are many alternatives out there but when i was in pain with a non booting machine, Acronis always saved me, and that’s what I finally need from a software like that.

Older Posts »