何故かIronPythonからDataGridにデータをバインドできない (1)
結果的には動いたんですが、Silverlight + IronPythonな環境でDataGridが使えるようになるまで大分手間取ってしまいました。Googleさんで検索してもほとんどヒットしない事例なのでメモを残しておきます。
なお、自分はIronPythonを使っていますが、他のDLR言語(Managed JScript、IronRuby)でも同様の事が発生するはずです。(対応方法も同じで良いはず…)
現象
何も考えずにSilverlight 2のSDKドキュメントのサンプルプログラムIronPythonに移植してみたが、どうもうまく動作しない。
ダメだった手順
ダメだったプログラム
- app.xaml
<UserControl x:Class="System.Windows.Controls.UserControl" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"> <Grid x:Name="layout_root" Background="White"> <data:DataGrid x:Name="datagrid" Margin="0,5,0,10" RowHeight="40" AutoGenerateColumns="False" > <data:DataGrid.Columns> <data:DataGridTextColumn Header="ID" Width="SizeToHeader" Binding="{Binding id}" FontSize="20" /> <data:DataGridTextColumn Header="name" Width="SizeToHeader" Binding="{Binding name}" FontSize="20" /> </data:DataGrid.Columns> </data:DataGrid> </Grid> </UserControl>
- app.py
from System.Windows import Application from System.Windows.Controls import UserControl # サンプルコードと同様にクラスを作ってみる # プロパティは2種類用意してみた class Item(object): def __init__(self, id, name): self.id = id self.name = name def _get_name(self): self._name def _set_name(self, val): self._name = val name = property(_get_name, _set_name) # バインドするデータを用意 source = [ Item('001', 'foo'), Item('002', 'bar'), Item('003', 'baz'), ] # xaml読み込み、DataGridへバインド root = Application.Current.LoadRootVisual(UserControl(), "app.xaml") root.datagrid.ItemsSource = source
原因
Googleさんで検索していたら以下のページを見つけた。
DevInfra-US: AgDatagrid and Silverlight Datagrid : how to build a dynamic datasource ?
要するに以下の通りらしい。
- DataGridにバインドするにはmanaged code(CLR)上に静的なclassが必要
- Dictonaryなどのような動的なデータはバインドできない
- DataGrid自体、バインドされるオブジェクトのプロパティをReflectionで取得する実装になっているらしい
- IronPythonのclass ≠ managed codeのclass
- 動的データをバインドしたい場合はReflectionで静的なclassを生成してしまえばよい
対応策
長くなってしまったので次回に続く。まだ書いてない。