Removing Ads with an IAP – the Declarative way

By | September 26, 2014

Microsoft’s XAML provides a way for us to define our UI in a declarative manner. Combined with databinding it means you should – in almost every case – never have to directly reference a UI control to accomplish some work. Add the MVVM design pattern in to the mix and I find myself “rethinking” any implementation where I think x:Name=”” is needed on a XAML control.

Let’s see how we can remove an ad control application-wide and upon purchase of its corresponding IAP without ever naming the control itself.

It’s worthwhile to note that if you put this control its own Grid Row, do not specify the height of the grid row. Instead, specify it as Auto. This ensures that when the Ad Control goes Collapsed, the grid row collapses to 0 as well, freeing up the piece of your UI previously eaten by the ad. Like so:

   1: <Grid.RowDefinitions>
   2:     <RowDefinition Height="*" /> <!--where all the real content goes-->
   3:     <RowDefinition Height="Auto" /> <!--where the ad control lives-->
   4: </Grid.RowDefinitions>

When working with Microsoft’s PubCenter ad control, the height and width of you ad are pre-determined. It’s therefore recommend you specify this in the control’s declaration (and oftentimes it won’t work if you don’t) like so:

   1: <UI:AdControl Grid.Row="1"
   2:               Height="80"
   3:               Margin="-12,12,-12,0"
   4:               Visibility="{Binding ShowAds, Converter={StaticResource BoolToVisibility}, Source={StaticResource ViewModel}}"
   5:               VerticalAlignment="Bottom"
   6:               AdUnitId="10862072"
   7:               ApplicationId="96378ca0-72b9-4bce-8739-16faeecd87e8" />

Notice right away the lack of naming of the control. To remove this control from the form, we bind its Visibility property to a ShowAds property on our ViewModel. For your reference, here’s the declaration of the ViewModel for the page (from its Resources area):

   1: <viewModels:MyViewModel x:Key="ViewModel" />

And here’s the code for that BoolToVisibility converter:

   1: public class BoolToVisibleConverter : IValueConverter
   2: {
   3:     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   4:     {
   5:         bool visibility = System.Convert.ToBoolean(value);
   6:         return visibility ? Visibility.Visible : Visibility.Collapsed;
   7:     }
   8:
   9:     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  10:     {
  11:         Visibility visibility = (Visibility)value;
  12:         return (visibility == Visibility.Visible);
  13:     }
  14: }

and its XAML declaration in the page’s Resources area:

   1: <myConverters:BoolToVisibleConverter x:Key="BoolToVisibility" />

Now that we’ve got all that in place, let’s see how we can both pull and trigger the state of Ad Showing in our app.

First thing’s first, the implementation of the state of the Ad Removal product we’re offering. In our ViewModel’s ShowAds property we put:

   1: public bool ShowAds
   2: {
   3:     get
   4:     {
   5:         var retVal = ProductPurchaseHelper.ShowAds;
   6:         return retVal;
   7:     }
   8: }

Our ViewModel might be INotifyPropertyChanged, but we don’t have to worry about that for this property as it’s getter-only. You’ll see later how we trigger its effects to the UI.

Now our ProductPurchaseHelper needs a way to purchase the Ad Removal product, of course:

   1: async internal static Task<bool> BuyProduct(string productId)
   2: {
   3:         var purchase = await CurrentApp.RequestProductPurchaseAsync(productId);
   4:         if (purchase.Status == ProductPurchaseStatus.Succeeded)
   5:         {
   6:             var info = await CurrentApp.LoadListingInformationByProductIdsAsync(new[] { productId });
   7:             if (info.ProductListings[productId].ProductType
   8:                 != Windows.ApplicationModel.Store.ProductType.Durable)
   9:             {
  10:                 await CurrentApp.ReportConsumableFulfillmentAsync(productId, purchase.TransactionId);
  11:             }
  12:             OnProductPurchased(productId);
  13:             return true;
  14:         }
  15:
  16:     return false;
  17: }

This method simply executes the Windows Phone Store purchase for an arbitrary product id and, if the product is consumable, reports it as fullfilled. Durable products don’t need this part executed. The salient point of what this does fires the OnProductPurchased event. This is the dude that’ll notify all its subscribers that a product got purchased – hopefully you can see where this is going :) Here’s what that event signature looks like:

   1: internal class ProductPurchasedEventArgs : EventArgs
   2: {
   3:     public ProductPurchasedEventArgs(string productId)
   4:     {
   5:         this.ProductId = productId;
   6:     }
   7:
   8:     public string ProductId { get; private set; }
   9: }
  10: internal event EventHandler<ProductPurchasedEventArgs> ProductPurchased;
  11: private void OnProductPurchased(string productId)
  12: {
  13:     if (this.ProductPurchased != null)
  14:     {
  15:         ProductPurchased(this, new ProductPurchasedEventArgs(productId));
  16:     }
  17: }

In our Page, we’ll want to subscribe to this event like so:

   1: ProductPurchaseHelper.ProductPurchased += (s, e) =>
   2: {
   3:     if (e.ProductId == "adremoval")
   4:     {
   5:         if (this.PropertyChanged != null)
   6:             PropertyChanged(this, new PropertyChangedEventArgs("ShowAds");
   7:     }
   8: };

This notifies the UI that the ShowAds property has changed, and it re-evaluates the Visibility of our AdControl. Since the product has been purchased, our Helper class will show as such when its ShowAds property is fetched again:

   1: internal static bool ShowAds
   2: {
   3:     get
   4:     {
   5:         var retVal = false;
   6:         ProductLicense license;
   7:         if (CurrentApp.LicenseInformation.ProductLicenses.TryGetValue("adremoval", out license))
   8:         {
   9:             retVal = license.IsActive;
  10:         }
  11:         return !retVal; // if retVal = true, then ad removal purchased, so DON'T show ads
  12:     }
  13: }
  14:

And the ad control’s visibility property will evaluate to ‘Collapsed’ and hide the control.

Hope you’ve found this helpful!

* Disclaimer: While pulling this code out of an existing app, I augmented the code right in the blog post to strip out my app’s infrastructure. As such this hasn’t been tested exactly as it’s written, but hopefully the idea comes across clearly if it doesn’t work out-of-the-box. Good luck!