23 November 2011

LINQ - On DataTable

You can transform a DataTable into a List of objects in a single statement using LINQ:
List<Customer> list = (from r in dataTable.AsEnumerable()
                       select new Customer {
                         Id      = r.Field<int>("Id"),
                         Name    = r.Field<string>("Name"),
                         Created = r.Field<datetime>("Created")
                       }).ToList();

To use AsEnumerable, you need to reference the assembly System.Data.DataSetExtensions (.NET 3.5) or include System.Data (.NET 4.5).

LINQ - List DataTable columns

How can you get a List of DataTable columns using LINQ?
The dataTable.Columns property cannot be queried with LINQ because it's a DataColumnCollection. Such a collection implements IEnumerable, but it's not a IEnumerable<DataColumn>, and therefore must be cast as such:
List<string> columnNames = (from c in dataTable.Columns.Cast<datacolumn>()
                            select c.ColumnName).ToList();

05 November 2011

Silverlight - Bindable DataGridColumn headers

When using a DataGrid in Silverlight, you might want to bind it's column headers. For localization purposes for instance. You can't bind the DataGridColumns Header property though, because it's not a dependency property. There is a work-around though, using a behaviour:

Interactivity

To use behaviour, you'll need System.Windows.Interactivity.dll. This one comes with Expression Blend. If you don't have that, you'll find it somewhere on the web.

The behaviour

The behaviour is in this class:
public class BindableColumnHeader : Behavior {
  public object Header {
    get { return GetValue(HeaderProperty); }
    set { SetValue(HeaderProperty, value); }
  }
  public static readonly DependencyProperty HeaderProperty = 
         DependencyProperty.Register("Header",
           typeof(object),
           typeof(BindableColumnHeader),
           new PropertyMetadata(
             new PropertyChangedCallback(HeaderBindingChangedHandler)));

  private static void HeaderBindingChangedHandler(
                      DependencyObject o,
                      DependencyPropertyChangedEventArgs e) {
    var behave = o as BindableColumnHeader;
    if (behave != null && behave.AssociatedObject != null)
      behave.AssociatedObject.Header = e.NewValue;
  }

  protected override void OnAttached() {
    if (this.AssociatedObject != null)
      this.AssociatedObject.Header = this.Header;
    base.OnAttached();
  }
}
It needs that .dll from before.

The DataGrid

To use the behaviour in the grid, you'll need both the interactivity dll (i:). and the behaviour class (synbus:). Then define a column like so:
<data:datagridtextcolumn binding="{Binding Customer}">
  <i:interaction.behaviors>
    <synbus:bindablecolumnheader header="{Binding Whatever}" />
  </i:interaction.behaviors>
</data:datagridtextcolumn>

02 November 2011

C# - Inline event handler

Sometimes an event handler is short enough for it to just put it inline, thus saving yet another method from being created. Let's say I have a custom event called OkEventHandler thats part of an object called RenameWindow. I attach the handler as follows:
renameWnd.Ok += new RenameWindow.OkEventHandler(delegate(object sender, EventArgs e) {
  //Whatever needs to be done
});
Or shorter:
renameWnd.Ok += (object sender, EventArgs e) => {
  //Whatever needs to be done
};
And even shorter:
renameWnd.Ok += delegate {
  //Whatever needs to be done
};
How much shorter can it get?
renameWnd.Ok += (sender, e) => DoOneThing();
Not much to it once you know.