Saturday, October 2, 2010
Halo Reach API C# Wrappers
There are Win Phone 7 versions and regular Windows class libraries. I even wrote a simple little proof of concept app that will get a player's details by Gamertag.
Everything is pretty untested at this point. But I'd like to add a video viewer to the Win Phone app sometime tomorrow.
See the project on Codeplex for more code samples and source code downloads.
Now Playing - Otis Taylor - Nasty Letter
Sunday, August 29, 2010
Show Custom In-House Ads in Win Phone 7 with MoAds
Just want the code? Get it here
There is also the sort of unsettling issue of Microsoft's Developer agreement being sort of fuzzy on advertising services (as pointed out by this MobileTechWorld article about MoAds).
At any rate, here's a brief run down of creating your own custom ad service using a new MVC 2 Website and some JSON services.
The Web Services Site - .Net MVC 2
In the example provided, I've created a new .Net MVC 2 website and added an AdController. The AdController is responsible for handling our AdRequests. In this case, we add two methods; Fetch and Click. The Fetch will be responsible for returning the Ad information (ImageUrl, AdText and ClickUrl) and the Click will redirect to the actual Ad Url after recording the client click.public ActionResult Fetch(string pubId, string clientId = "")
{
// TODO: You'd probably want to keep track of fetches by PubId for analytics, but this is just a demo.
var ad = AdRepository.GetRandomAd();
Impression impression;
var clickUrl = GenerateClickUrl(ad, out impression);
ImpressionRepository.Impressions.Add(impression);
return new JsonResult()
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new FetchResponse()
{
ClickUrl = clickUrl,
AdText = ad.AdText,
ImageUrl = ad.ImageUrl
}
};
}
public ActionResult Click(string id)
{
// TODO: Track the click for analytics and what-not.
var impression = ImpressionRepository.Impressions.FirstOrDefault(x => x.Token == id);
if (impression == null)
return View(); // TODO: return not found result.
var ad = AdRepository.GetAdById(impression.AdId);
return new RedirectResult(ad.AdUrl);
}
Creating a Custom Ad Adapter
The Custom Ad Adapter generally has an underlying service component (in our example it's called CustomAdService) that calls out to some service and gets some ad information, massages the response and fires our GotAdResponse event. Here's a brief run down of what our CustomAdAdapter class looks like.
public class CustomAdAdapter : IAdAdapter
{
private CustomAdService adService = new CustomAdService();
/// <summary>
/// Gets or sets the publisher id.
/// </summary>
/// <value>The publisher id.</value>
public string PublisherId { get; set; }
/// <summary>
/// Gets or sets the client id.
/// </summary>
/// <value>The client id.</value>
public string ClientId { get; set; }
public CustomAdAdapter()
{
adService.GotResult += new EventHandler<Service4u2.Common.EventArgs<CustomAdFetchResponse>>(adService_GotResult);
adService.GotError += new EventHandler<Service4u2.Common.EventArgs<Exception>>(adService_GotError);
}
void adService_GotError(object sender, Service4u2.Common.EventArgs<Exception> e)
{
if (GotError != null)
GotError(this, e);
}
void adService_GotResult(object sender, Service4u2.Common.EventArgs<CustomAdFetchResponse> e)
{
var adResponse = new AdResponse()
{
AdText = e.Argument.AdText,
ImageUrl = e.Argument.ImageUrl,
ClickUrl = e.Argument.ClickUrl
};
if (GotAdResponse != null)
GotAdResponse(this, new Service4u2.Common.EventArgs<AdResponse>() { Argument = adResponse });
}
#region IAdAdapter Members
public event EventHandler<Service4u2.Common.EventArgs<AdResponse>> GotAdResponse;
public event EventHandler<Service4u2.Common.EventArgs<Exception>> GotError;
public void GetAdResponseAsync()
{
adService.FetchAdAsync(this.PublisherId, this.ClientId);
}
#endregion
}
Hooking up our Custom Ad Adapter in XAML
Once we have our Custom Ad Adapter in place we can plug it in to our AdDisplay control and start serving ads.
<!-- Custom Ad Service example -->
<moad:AdDisplay
Style="{StaticResource AnimationAdMobStyle}"
VerticalAlignment="Bottom"
Foreground="White"
RefreshSeconds="30">
<moad:AdDisplay.AdAdapter>
<local:CustomAdAdapter
PublisherId="SomePubId"
ClientId="SomeClientId"/>
</moad:AdDisplay.AdAdapter>
</moad:AdDisplay>
And that's about it. Hopefully I'll find some other ad service providers to implement soon. If anyone has any recommendations I'd be happy to hear them.
Grab the updated example source from here or the Project Page at BitBucket (Codeplex is still Garbage).
Now Playing - Notorious B.I.G - Mo Money Mo Problems
Saturday, August 28, 2010
MoAds - Custom Win Phone 7 Ad Control with AdMob support
Update 2: Microsoft has released a much better ad serving solution than AdMob, this was just a stop gap in case nothing official was released. This control is old and busted, check out the Microsoft Ad SDK for the new hotness.
After seeing a project on CodePlex that allowed you to display AdMob ads in a Win Phone 7 application, I decided it would be a good project for another custom control.
Custom Styling, Animation and Templates
The main problem I saw with the existing control was that it didn't take advantage of the styling and "Blendability" of the Win Phone 7 platform. Basically, the control used a web browser control to display an HTML template that was updated with ad information.
Here is an example of three different styles for the same template, the top is the default template, the middle is a text only style, and the bottom shows a fading animation when the ads are refreshing. The animations are helped by utilizing the three states for the AdDisplay control; Loading, Normal and Error.
Custom Ad Providers
Another issue I saw was that it relied solely on AdMob, with very little flexibility for hooking up another Ad service (like a rumored Bing Mobile Ad Service), so I added an adapter pattern to the control.
Here is an example of using the provided AdMob Adapter with the control (notice this can all be done in XAML, no code behind).
<!-- Default template example -->
<moad:AdDisplay
Height="70"
VerticalAlignment="Top"
Foreground="White"
RefreshSeconds="30">
<moad:AdDisplay.AdAdapter>
<moad:AdMobAdapter
PublisherId="YourPublisherID"
CookieString="YourCookieString"
AdKeywords="Boston"
UseTestMode="True"/>
</moad:AdDisplay.AdAdapter>
</moad:AdDisplay>
I'm hoping to put up another post to talk about creating a custom "In-House" ad provider.
You can download the source from my DropBox account, or at the created project on Codeplex called MoAds.
Now Playing - Goodie Mob - Get Rich to This
Thursday, July 29, 2010
Clearable TextBox Custom Control
It looks like I've got most of the functionality replicated, including adding two states to help with animations. The states are "Normal" and "Cleared". By default, the Cleared state will cause the clear button text to flash red briefly. You can also now set the ClearButtonTemplate and the ClearButtonContent if you want. In the picture you can see I've set the ClearButtonContent to Clear and used the default template.
<clr:ClearableTextBox
Text="{Binding SomeText, Mode=TwoWay}"
ClearButtonContent="Clear"
VerticalAlignment="Top"/>
I haven't tested any custom state animations, only the default ones that are included. Feel free to let me know if you find any problems. The source and binaries are available below.
Clearable TextBox Custom Control Source
Now Playing: The Roots - Don't Say Nuthin
Wednesday, July 28, 2010
A Clearable TextBox for Win Phone 7
After seeing a tweet about the lack of a clearable text box similar to the IPhone by Eric Malamisura, I was inspired to whip together a simple control that fills this need.
Here is some code for the control, in case you don't want to download the full example. Just create a new UserControl called ClearableEditBox and paste these parts in the relevant places.
<!-- Put inside your new UserControl -->
<Grid x:Name="LayoutRoot">
<TextBox
MinWidth="50"
Text="{Binding ElementName=uiThis, Path=Text, Mode=TwoWay}"
x:Name="editBox"/>
<Button
MinWidth="30"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="clrBtn_Click"
x:Name="clrBtn">
<Button.Template>
<ControlTemplate>
<TextBlock
FontSize="25"
Margin="0 0 20 0"
Foreground="Gray"
FontWeight="Bold"
Text="X"/>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
// Put inside your code behind for your new UserControl.
public partial class ClearableTextBox : UserControl, INotifyPropertyChanged
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
// Using a DependencyProperty as the backing store for EditText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ClearableTextBox), new PropertyMetadata(string.Empty, HandleTextChanged));
public ClearableTextBox()
{
InitializeComponent();
}
private static void HandleTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var box = obj as ClearableTextBox;
if (null != box)
box.OnPropertyChanged("Text");
}
private void clrBtn_Click(object sender, RoutedEventArgs e)
{
Text = string.Empty;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (null != PropertyChanged)
PropertyChanged(null, new PropertyChangedEventArgs(name));
}
#endregion
}
You can also download a sample project containing the control here.
Clearable TextBox UserControl
Now Playing: Eminem - Airplanes
Monday, July 26, 2010
Updated Win Phone 7 Busy Service That Does Not Change RootVisual
As a result, I've updated my sample to not require wrapping the root level PhoneApplicationFrame with a Grid. It turns out, most pages already have a Grid as their LayoutRoot element and you can just pass this in to a new RootPaneBusyService and use it in the same manner. So instead of passing the App.Current.RootVisual as Grid, we pass the LayoutRoot.
protected override void OnNavigatedTo( System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var busyServ = new RootPanelBusyService(this.LayoutRoot);
this.DataContext = new MainPageVM(busyServ);
}
I've also updated the CreateBusyElement method to detect how many rows and columns are in the passed in root visual and set the ColumnSpan and RowSpan accordingly.
// Set the row and column span's if the root is a grid.
if (rootVisual is Grid)
{
var gridRoot = rootVisual as Grid;
int rowSpan = 1;
if (gridRoot.RowDefinitions != null)
rowSpan = gridRoot.RowDefinitions.Count + 1;
int columnSpan = 1;
if (gridRoot.ColumnDefinitions != null)
columnSpan = gridRoot.ColumnDefinitions.Count + 1;
Grid.SetRowSpan(root, rowSpan);
Grid.SetColumnSpan(root, columnSpan);
}
Download the updated sample
Create a Win Phone 7 Busy Service with Loady animation
Update 2: I've updated my example to not require changing the RootVisual. But you will still need to have a Grid as the Root of your Page. Check out the Updated Busy Service.
I've been spending a lot of time working on data driven Win Phone 7 apps in the past couple weeks and one of the most useful things I've created is a simple Busy Service for Win Phone 7 apps.

/// <summary>
/// An interface for busy services.
/// </summary>
public interface IBusyService
{
bool IsBusyShown { get; }
void ShowBusy(string message);
void ShowBusy(TimeSpan timeToShow, string message);
void ShowBusy(double milliSecondsToShow, string message);
void HideBusy(double millisecondsToWait);
void HideBusy(TimeSpan delay);
void HideBusy();
}
I decided to implement a RootPanelBusyService, which basically means that it expects a "Panel" type of element, a Grid for example, at the RootVisual. The problem with the Win Phone 7 Beta update is that the RootVisual is no longer defined in the App.Xaml, so it would seem like you can't just wrap the Root level Phone Application Frame in a Grid. It turns out, it just takes a little more work, if you open up the App.xaml.cs and take a look at the CompleteInitializePhoneApplication method you will see where the RootVisual is assigned. So with a little code we can add a Grid wrapper around the PhoneApplicationFrame and have a nice place to add our Busy Loady icon.
// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
{
// Add a Grid wrapper around the Root application frame.
var root = new Grid();
root.Children.Add(RootFrame);
RootVisual = root;
}
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
Now that we have our Grid at the Root, we can instantiate a RootPanelBusyService and pass it to our ViewModel to start "Getting Busy...".
// From MainPage.xaml.cs
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (App.Current.RootVisual is Grid)
{
var busyServ = new RootPanelBusyService(App.Current.RootVisual as Grid);
this.DataContext = new MainPageVM(busyServ);
}
}
// In our MainPage View Model (MainPageVM.cs)
/// <summary>
/// A view model for the Main Page.
/// </summary>
public class MainPageVM : ViewModelBase
{
/// <summary>
/// The busy service to use...
/// </summary>
private IBusyService busyService;
/// <summary>
/// Gets or sets the do busy command.
/// </summary>
/// <value>The do busy command.</value>
public ICommand DoBusy { get; private set; }
public MainPageVM(IBusyService busyServ)
{
busyService = busyServ;
DoBusy = new DelegateCommand<object>(HandleDoBusy);
}
/// <summary>
/// Handles the do busy command.
/// </summary>
/// <param name="arg">Unused.
private void HandleDoBusy(object arg)
{
busyService.ShowBusy(2000, "Getting Busy...");
}
}
And there you have it, you've got a simple and easy to use busy service for your long running operations. One other trick that I occasionally use it to set a Busy Service static property on my App class, so all ViewModels have easy access to it. To do this, just add a static property to your App class, and assign it after setting the RootVisual, like so:
// Easy access to the busy service.
public static IBusyService BusyService { get; private set; }
// Rest of this class omitted for brevity....
// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
{
// Add a Grid wrapper around the Root application frame.
var root = new Grid();
root.Children.Add(RootFrame);
RootVisual = root;
// Set our easy access busy service property.
BusyService = new RootPanelBusyService(root);
}
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
If you don't want to download the full example project to get the RootPanelBusyService implementation, here is the source, but you'll need to create your own Loady graphic / control.
/// <summary>
/// An interface for busy services.
/// </summary>
public interface IBusyService
{
bool IsBusyShown { get; }
void ShowBusy(string message);
void ShowBusy(TimeSpan timeToShow, string message);
void ShowBusy(double milliSecondsToShow, string message);
void HideBusy(double millisecondsToWait);
void HideBusy(TimeSpan delay);
void HideBusy();
}
/// <summary>
/// A busy service that expects a Panel / Grid as the root visual.
/// </summary>
public class RootPanelBusyService : IBusyService
{
private UIElement currentBusyElement;
private Panel rootVisual;
/// <summary>
/// Initializes a new instance of the <see cref="RootPanelBusyService"> class.
/// </see></summary>
/// The root visual element.
public RootPanelBusyService(Panel rootVisualElement)
{
rootVisual = rootVisualElement;
}
#region IBusyService Members
private bool _busyShown = false;
public bool IsBusyShown
{
get { return _busyShown; }
}
public void ShowBusy(double milliSecondsToShow, string message = "Loading...")
{
ShowBusy(TimeSpan.FromMilliseconds(milliSecondsToShow), message);
}
public void ShowBusy(TimeSpan timeToShow, string message = "Loading...")
{
ShowBusy(message);
ThreadPool.QueueUserWorkItem(new WaitCallback(time =>
{
Thread.Sleep((TimeSpan)time);
// Hide the busy after a sleep.
rootVisual.Dispatcher.BeginInvoke(() => HideBusy());
}), timeToShow);
}
public void ShowBusy(string message = "Loading...")
{
_busyShown = true;
var busyEl = CreateBusyElement(message);
busyEl.Opacity = 0;
try
{
if (rootVisual is Panel)
{
var root = rootVisual;
root.Children.Add(busyEl);
var anim = CreateAnimation(busyEl, Grid.OpacityProperty, 0.8, 0.00, 900, EasingMode.EaseOut);
var story = new Storyboard();
story.Children.Add(anim);
story.Begin();
}
}
catch
{
Debug.WriteLine("Problem showing busy.");
}
currentBusyElement = busyEl;
}
public void HideBusy(double milliseconds)
{
HideBusy(TimeSpan.FromMilliseconds(milliseconds));
}
public void HideBusy(TimeSpan delay)
{
var root = rootVisual;
ThreadPool.QueueUserWorkItem(new WaitCallback((arg) =>
{
Thread.Sleep(delay);
((Panel)arg).Dispatcher.BeginInvoke(() =>
{
HideBusy();
});
}), root);
}
public void HideBusy()
{
try
{
if (rootVisual is Panel)
{
var root = rootVisual;
var anim = CreateAnimation(currentBusyElement, Grid.OpacityProperty, 0.00, .80, 1000, EasingMode.EaseOut);
var story = new Storyboard();
story.Children.Add(anim);
story.Begin();
// Remove the element a second later; I do it this way because StoryCompleted is flaky.
ThreadPool.QueueUserWorkItem(new WaitCallback(obj =>
{
Thread.Sleep(900);
root.Dispatcher.BeginInvoke(() =>
{
root.Children.Remove(currentBusyElement);
currentBusyElement = null;
});
}), null);
}
}
catch
{
Debug.WriteLine("Problem hiding busy.");
}
_busyShown = false;
}
#endregion
/// <summary>
/// Creates the busy element; A Loady with a text block underneath.
/// </summary>
/// The message to show below the loady.
private UIElement CreateBusyElement(string message = "Loading...")
{
// create a grid to hold the loady and swallow the entire screen.
var root = new Grid()
{
Background = new SolidColorBrush(Colors.Black)
};
// The spinny loady thingy...
root.Children.Add(new Loady()
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
});
// The text below the loady...
root.Children.Add(new TextBlock()
{
Text = message,
Margin = new Thickness(0, 150, 0, 0),
FontSize = 30,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = System.Windows.VerticalAlignment.Center,
Foreground = new SolidColorBrush(Colors.White)
});
return root;
}
/// <summary>
/// A helper method for creating double animations.
/// </summary>
public DoubleAnimation CreateAnimation(DependencyObject obj, DependencyProperty prop, double value, double milliseconds, EasingMode easing = EasingMode.EaseOut)
{
var from = Convert.ToDouble(obj.GetValue(prop));
return CreateAnimation(obj, prop, value, from, milliseconds, easing);
}
/// <summary>
/// A helper method for creating double animations.
/// </summary>
public DoubleAnimation CreateAnimation(DependencyObject obj, DependencyProperty prop, double value, double from, double milliseconds, EasingMode easing = EasingMode.EaseOut)
{
CubicEase ease = new CubicEase() { EasingMode = easing };
DoubleAnimation animation = new DoubleAnimation
{
Duration = new Duration(TimeSpan.FromMilliseconds(milliseconds)),
From = from,
To = value,
FillBehavior = FillBehavior.HoldEnd,
EasingFunction = ease
};
Storyboard.SetTarget(animation, obj);
Storyboard.SetTargetProperty(animation, new PropertyPath(prop));
return animation;
}
}
Now Playing: The Roots - Get Busy
Tuesday, July 13, 2010
Win Phone 7 "Words" Game - Mo Words
My wife and I have been playing a lot of word games lately on our IPhones. I've also been playing around with the Win Phone 7 SDK and I've been looking for a good project to work with. So, as a result, I made a little "Words" game called Mo Words.
I've just recently got it to a point where I could play a whole game. But there is still some work to be done for the play notifications (I'm hoping to get Push notifications working this weekend).
The game uses an MVC 2 website returning JSON responses as it's service layer. I hope to put together a couple posts on how I make data driven win phone apps with MVC 2 websites, including how to authenticate to an MVC 2 site and all that.
So, without further ado, here is a demo video (sorry it's choppy, the loading animations and dragging don't match the smoothness of the actual game, it's much better in person) and some screen shots.





Now Playing: Animal Collective - My Girls




