通过 IAP 移除广告 - 声明式方式
微软的 XAML 提供了一种以声明方式定义 UI 的方法。结合数据绑定,这意味着在几乎所有情况下,您都不应该直接引用 UI 控件来完成某项工作。再加上 MVVM 设计模式,我发现自己会“重新思考”任何
微软的 XAML 提供了一种以声明方式定义 UI 的方法。结合数据绑定,这意味着在几乎所有情况下,您都不应该直接引用 UI 控件来完成某项工作。再加上 MVVM 设计模式,我发现自己会“重新思考”任何需要在 XAML 控件上使用 x:Name="" 的实现。
让我们看看如何在不命名控件的情况下,在整个应用程序范围内以及购买其对应的 IAP 后移除广告控件。
值得注意的是,如果您将此控件放在自己的 Grid 行中,请不要指定 grid 行的高度。而是将其指定为 Auto。这可确保当广告控件变为 Collapsed 时,grid 行也会折叠为 0,从而释放 UI 中之前被广告占据的部分。例如:
1: <Grid.RowDefinitions> 2: <RowDefinition Height="*" /> <!--where all the real content goes--> 3: <RowDefinition Height="Auto" /> <!--where the ad control lives--> 4: </Grid.RowDefinitions>
在使用微软的 PubCenter 广告控件时,广告的高度和宽度是预先确定的。因此,建议您在控件的声明中指定这些值(并且通常如果未指定,则无法正常工作),例如:
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" />
请注意,缺少控件的命名。要从表单中移除此控件,我们将 Visibility 属性绑定到 ViewModel 上的 ShowAds 属性。为了您的参考,这是页面 ViewModel 的声明(来自其 Resources 区域):
1: <viewModels:MyViewModel x:Key="ViewModel" />
这是该 BoolToVisibility
转换器的代码:
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: }
以及它在页面 Resources 区域中的 XAML 声明:
1: <myConverters:BoolToVisibleConverter x:Key="BoolToVisibility" />
现在我们已经准备好所有这些,让我们看看如何拉取和触发应用程序中广告显示的状态。
首先,我们正在提供的广告移除产品的状态实现。在 ViewModel 的 ShowAds
属性中,我们放置:
1: public bool ShowAds 2: { 3: get 4: { 5: var retVal = ProductPurchaseHelper.ShowAds; 6: return retVal; 7: } 8: }
我们的 ViewModel 可能是 INotifyPropertyChanged
,但我们不必担心这个属性,因为它仅具有 getter。稍后您将看到我们如何触发其对 UI 的影响。
现在我们的 ProductPurchaseHelper
需要一种购买广告移除产品的方法,当然。
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: }
此方法只是执行 Windows Phone Store 中任意产品 ID 的购买,并且如果产品是可消耗的,则将其报告为已完成。持久性产品不需要执行此部分。此操作的关键点是触发了 OnProductPurchased
事件。这是通知所有订阅者产品已购买的家伙 – 希望您能看到这一点 :) 这是该事件签名的样子:
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: }
在我们的页面中,我们将希望订阅此事件,如下所示:
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: };
这会通知 UI ShowAds
属性已更改,并重新评估 AdControl 的 Visibility。由于产品已购买,我们的 Helper 类在再次获取其 ShowAds
属性时会显示为已购买。
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:
广告控件的 Visibility 属性将评估为“Collapsed”并隐藏控件。
希望这能对您有所帮助!
* 免责声明:在从现有应用程序中提取此代码时,我直接在博客文章中增强了代码,以去除我的应用程序的基础设施。因此,这尚未完全按照编写的方式进行测试,但希望如果它不能开箱即用,这个想法也能清楚地传达出来。祝你好运!