Im ersten Blogeintrag habe ich an dieser Stelle C# dynamic kurz vorgestellt. Der 2. Teil des Eintrages ging es um das DynamicObject und wie man Member hinzufügen kann. Nun wollen wir das ganze in einem einfachen WPF Beispiel darstellen.
Um dies zu erreichen, wird die Klasse “DynamicObject” aus dem vorigen Beispiel benötigt. Wir erstellen uns in Visual Studio ein neues Projekt vom Typ “WPF”.
Nun erstellen wir uns eine neue Methode, welche Daten vom Yahoo Webservice runter lädt. Wir wollen uns die Finanzdaten der letzten Monate anzeigen lassen (zugegeben, anhand der aktuellen Kriese vermutlich nicht das beste Beispiel …). Damit wir das erreichen können, brauchen wir zuerst Daten. Hierfür gehen wir auf “finance.yahoo.com” und wählen dort “MSFT” als Symbol aus.
Auf dieser Seite wählen wir die Kategorie “Historical Prices” aus. Ganz unten auf der Seite befindet sich ein Link “Download to Spreadsheet”.
Das schöne daran ist, das es sich hierbei um eine CSV-Datei handelt. Nun macht auch unser “DynamicCSVObject” Sinn ;). wichtig wäre auch noch, die Zeit etwas einzuschränken – denn sonst geht es vom 1. Tag des IPO (Initial Public Offering) bis heute – und das sind mehrere MB an Daten.
Nun, da wir den Link haben, müssen wir die Daten nur noch mittels WebRequest downloaden. Hierfür erstellen wir uns eine neue Methode “DownloadData”. Für die Methode wird noch eine Liste vom generischen Typ “dynamic” benötigt, welche als private Variable definiert wird.
private List<dynamic> lst;
Für unser CSV-Objekt (DynamicCSVObject) benötigen wir einen Header welcher als Name für die Methoden dient. Hierfür definieren wir einen Array.
private void DownloadData()
{
lst = new List<dynamic>();
dynamic obj;
string[] header;
danach wird ein WebRequest auf die Website gestellt. Das ganze wird in einem StreamReader eingelesen.
var request = WebRequest.Create("http://ichart.finance.yahoo.com/table.csv?s=MSFT&a=11&b=13&c=2008&d=09&e=28&f=2009&g=d&ignore=.csv");
var response = request.GetResponse() as HttpWebResponse;
var reader = new StreamReader(response.GetResponseStream());
Im nächsten Schritt wird die CSV-Datei anhand von Zeilenumbrüchen und Komas “,” gespalten. Dies können wir sehr einfach in einer Zeile dank LinQ lösen. Ferner holen wir uns aus diesem Set die Headers raus. Diese enthalten Werte “SymbolName”, “Date”, “Open”, …
var set = reader.ReadToEnd().Trim().Split('\n').Select(l => l.Split(','));
header = set.First();
Danach müssen die einzelnen Objekte nur noch angelegt werden. Hierfür iterieren wir einfach über die Items in der Collection und fügen diese der Liste hinzu.
foreach (var itm in set.Skip(1))
{
obj = new DynamicCSVObject(header, itm);
lst.Add(obj);
}
Wichtig ist nun noch, das die Daten geladen wird und die ItemsSource der ListBox gebunden wird. (Die Listbox muss in XAML noch definiert werden, mehr dazu später)
public MainWindow()
{
InitializeComponent();
DownloadData();
SymbolResults.ItemsSource = lst;
}
Wir gehen einfach mal davon aus, das wir an “Date”, “Open” und “Close” binden wollen (die erst zur Laufzeit vorhanden sind).
<ListBox Name="SymbolResults">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock FontSize="16" Foreground="DarkBlue" Text="{Binding Path=Date}"></TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Foreground="Black" Text="Startwert: " />
<TextBlock FontSize="12" Foreground="Black" Text="{Binding Path=Open}" />
<TextBlock FontSize="12" Foreground="Black" Text="Endwert: " />
<TextBlock FontSize="12" Foreground="Black" Text="{Binding Path=Close}" />
</StackPanel>
<Rectangle Height="2" Fill="Black" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Wien man hier sieht ist auch Datenbindung möglich. Bis zur Laufzeit wissen wir jedoch nicht, welche Member überhaupt zur Verfügung stehen. Wenn dann aber die Laufzeit da ist :) kann man genau so vorgehen wie man es auch sonst machen würde.
