Land Rovers, .Net en meer!
Binding a WPF DataGridColumn to a LINQ result
I’ve been tinkering with Visual Studio 2010 Beta1 and the .Net 4 framework. One of the things that I’ve tried is filling a DataGrid with the results of a LINQ query.
Consider the following code:
C#
var voyages = from voyage in entities.Voyage
select new { Number = voyage.Number, ETA = voyage.StartTime };
dataGridTest.ItemsSource = voyages;
XAML
<DataGrid Name="dataGridTest">
<DataGrid.Columns>
<DataGridTextColumn Header="Number" Binding="{Binding Path=Number}" />
<DataGridTextColumn Header="ETA" Binding="{Binding Path=ETA}" />
</DataGrid.Columns>
</DataGrid>
Seems straightforward enough, doesn’t it? Well it does but when you try to run it, it’ll crash and burn with the following exception:
InvalidOperationException: A TwoWay or OneWayToSource binding cannot work on the read-only property ‘Number’
The reason that the InvalidOperationException gets thrown is that the Binding used to bind the column to a property is a TwoWay binding, by default!
But why should (and is) this be a problem? Well, because the result from the LINQ is a new class that contains only get-properties. This is by design because an anonymous type can only contain get-only properties as is written on MSDN:
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type.
There are two workarounds for this problem, one is simply to add Mode=OneWay to the Binding property of the DataGridTextColumn. This will tell the DataGrid (ultimately the Binding) that it should not attempt to write data back to the bound object.
The other workaround is not to use an anonymous type. If you need to be able to change data in the result set this is probably the way to go. By defining a type that contains the properties you want to bind on you can tell LINQ to return that specific type and not an anonymous one.
For example:
C#
public class VoyageResult {
public int Number { get; set; }
public DateTime ETA { get; set; }
}
var voyages = from voyage in entities.Voyage
select new VoyageResult()
{
Number = voyage.Number,
ETA = voyage.StartTime
};
voyages will now contain a list of VoyageResults instead of a generated anonymous type (with exactly the same properties!) If you bind this list to the DataGrid it will use the default TwoWay binding without complaints.
| Print artikel | Dit bericht is gepost door Sander op augustus 26, 2009 om 3:42 pm uur en is gearchiveerd onder .Net. Volg reacties op dit bericht via RSS 2.0. Reacties zijn momenteel uitgeschakeld, maar je kunt trackback van je eigen site. |
Commentaar is gesloten.