2011 was a good year (mostly). I got into wp7 development and released a couple of somewhat successful applications. In mid December I noticed that I am getting close to a total of 100k downloads and took some drastic measures to reach that number by the end of the year. So now (a week later) I’m glad to report that around December 29th I did it. Next stop – 1 million downloads…
Gadget of the year
For me the gadget of the year (2011) is the $79 kindle. Not the Fire. Not the iPad. The cheapest kindle. I would have purchased the kindle touch for $20 more but it has a serious design flow – if you (like me) dislike fingerprints on the screen it can drive you crazy. The cheaper model has buttons for prev and next page and is actually a little bit smaller and lighter than the touch. You do not need a keyboard if you own a computer and I’m undecided on the 3G. And it is so small and thin and light. I read more books last moth (since I have it) than any other month in the year. What makes it really great is that you don’t have to wait for 2 days for your book to arrive from amazon, you can start reading in a minute. My wife has a “vintage” second generation kindle and she loves it but I can see the envy in her eyes… The only thing that feels wrong is that the ebooks are not really cheaper than the paper ones and even some times are more expensive…
QR Business Cards
QR (quick read) barcodes are a quick and easy way to share information between mobile devices. “QR business card” allows you to create several different business cards with different information in them. For example you can have a personal and work card as well as one with just your e-mail address. To share a card tap on the card to open it and then go to the page with the QR barcode. Let your friend scan the barcode with his mobile device. To receive a card on a Windows Phone 7 device open Bing and tap on the Visual Search icon. Scan the QR barcode and import it in your contact list. On iPhone, Blackberry or Android use an appropriate QR reader application. Never run out of business cards again!
Orlando GiveCamp
The first (annual?) Orlando GiveCamp was held in the weekend of October 21-23 and I even helped a little bit with the organization. More than 50 people showed up and worked on about 10 projects for different non-profit organizations from Central Florida. It was an interesting experience, new people, smart people, good food and tons of fun. I am now a WordPress expert and MVC3 beginner 🙂 Hope to do that again next year…
ONETUG
After helping with the Orlando Code Camp this year I was invited to join the board of ONETUG. I will be responsible for the web site as well as anything else “tech”. I even hope to do a little talk in front of the group some time in the future (what topic?). ONETUG is my new home. I’m can’t be happier…
INotifyPropertyChanged
The thing that bothers me the most about MVVM and similar patterns is the ugly code that you have to write just to implement INotifyPropertyChanged interface on you view models. So instead of my nice and shiny class “A” I need to write the horrible monster “B”.
// exhibit "A"
class Sale
{
public string Name { get; set; }
public Decimal Price { get; set; }
public Decimal Quantity { get; set; }
public Decimal Total { get { return Price * Quantity; } }
}
// exhibit "B"
class Sale : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
private Decimal price;
public Decimal Price
{
get { return price; }
set
{
if (price != value)
{
price = value;
NotifyPropertyChanged("Price");
NotifyPropertyChanged("Total");
}
}
}
private Decimal quantity;
public Decimal Quantity
{
get { return quantity; }
set
{
if (quantity != value)
{
quantity = value;
NotifyPropertyChanged("Quantity");
NotifyPropertyChanged("Total");
}
}
}
public Decimal Total { get { return Price * Quantity; } }
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Everybody can see what the problem with “B” is. Not only the code is ten times longer but it does not mean or do anything particularly fancy. The code that I can live with looks something like this:
// exhibit "C"
class Sale : BaseClass
{
[NotifyPropertyChanged]
public string Name { get; set; }
[NotifyPropertyChanged("Price", "Total")]
public Decimal Price { get; set; }
[NotifyPropertyChanged("Quantity", "Total")]
public Decimal Quantity { get; set; }
public Decimal Total { get { return Price * Quanitity; } }
}
As of this moment I do not know how to make “C” happen. My guess would be that we either need some (pre-) compiler magic or something like an aspect (as in AOP). I am willing to bet $20 that something like this will either happen in one of the MVVM frameworks very soon (and that will be my framework of choice) or Microsoft will implement it in the next version of C#.
From WinForms to WPF
A nice series of articles on Reed Copsey’s blog.
MSDN DevLabs
DevLabs is a place where Microsoft employees develop side projects that will eventually be included in future Microsoft products. “Experiment, evaluate, and then join [us] in the conversation.”
The Essence of LINQ
A lovely read at Bart De Smet’s blog about how LINQ works…
Application Settings
The .net framework provides a powerful way to provide application settings in app.config file. There is also the ability to use command line parameters but they are accessed in completely different fashion. I created couple of classes to simplify parameters handling and provide a declarative syntax.
public class MyAppsSettings : Settings
{
[CommandLineParam("/u")]
public string UserName { get; set; }
[CommandLineParam("/p")]
public string Password { get; set; }
[ConnectionString("MyDB")]
public string MyDBConnStr { get; set; }
[AppSetting("Mode")]
public string Mode { get; set; }
[AppSetting("DefaultMode", "Test")]
public string DefaultMode { get; set; }
}
Here is the complete source code:
[AttributeUsage(AttributeTargets.Property)]
public class CommandLineParamAttribute : Attribute
{
public string Name { get; set; }
public string DefaultValue { get; set; }
public CommandLineParamAttribute(string Name)
{
this.Name = Name;
this.DefaultValue = string.Empty;
}
public CommandLineParamAttribute(string Name, string DefaultValue)
{
this.Name = Name;
this.DefaultValue = DefaultValue;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class ConnectionStringAttribute : Attribute
{
public string Name { get; set; }
public ConnectionStringAttribute(string Name)
{
this.Name = Name;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class AppSettingAttribute : Attribute
{
public string Key { get; set; }
public string DefaultValue { get; set; }
public AppSettingAttribute(string Key)
{
this.Key = Key;
this.DefaultValue = string.Empty;
}
public AppSettingAttribute(string Key, string DefaultValue)
{
this.Key = Key;
this.DefaultValue = DefaultValue;
}
}
public class Settings
{
public Settings()
{
CommandLineParams clp = new CommandLineParams();
Type type = this.GetType();
foreach (PropertyInfo pi in type.GetProperties())
{
object[] arr = pi.GetCustomAttributes(true);
foreach (object o in arr)
{
if (o is CommandLineParamAttribute)
{
string name = ((CommandLineParamAttribute)o).Name;
string value = ((CommandLineParamAttribute)o).DefaultValue;
if (clp.Contains(name)) value = clp[name];
pi.SetValue(this, value, null);
}
if (o is ConnectionStringAttribute)
{
string name = ((ConnectionStringAttribute)o).Name;
string conn = ConfigurationManager.ConnectionStrings[name].ConnectionString;
pi.SetValue(this, conn, null);
}
if (o is AppSettingAttribute)
{
string key = ((AppSettingAttribute)o).Key;
string value = ((AppSettingAttribute)o).DefaultValue;
if (ConfigurationManager.AppSettings.AllKeys.Contains(key))
value = ConfigurationManager.AppSettings[key];
pi.SetValue(this, value, null);
}
}
}
}
}
