シナリオから始めましょう:
UserControl内にItemsControlがあります。このItemsControlには、コードビハインドで作成および追加される動的に作成されたDataTemplateがあります。コードビハインドでDataTemplateを作成する良い方法がないように思われるため、DataTemplateのxamlコードをプログラムで文字列に生成し、XamlReaderを使用してそこからDataTemplateオブジェクトを作成する必要がありました。
StringBuilder stringBuilder = new StringBuilder();
XmlWriter xmlWriter = XmlWriter.Create(stringBuilder);
... // use xmlWrite to generate desired xaml
// substring is use to cut out the xml declaration
DataTemplate template = (DataTemplate)XamlReader.Load(stringBuilder.ToString().Substring(39));
myItemsControl.ItemTemplate = template;
生成されたXAMLコードは次のようになり、実際に使用されます(アイテムは期待どおりにレンダリングされます)。
<DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid HorizontalAlignment="Stretch" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding b0}" Grid.Column="0" />
<TextBox Text="{Binding b1, Converter={StaticResource customConverter}}" HorizontalAlignment="Stretch" Grid.Column="1" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b2, Converter={StaticResource customConverter}}" HorizontalAlignment="Stretch" Grid.Column="2" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b3, Converter={StaticResource customConverter}}" HorizontalAlignment="Stretch" Grid.Column="3" LostFocus="TxtAttribute_LostFocus" IsReadOnly="True" />
</Grid>
不思議に思うかもしれませんが、コントロールをレンダリングするためにXamlReaderがxmlns属性を必要とします。そうしないと、コードに到達したときに例外が発生します。
私の問題:
アイテムが期待どおりに表示され、データが正しくバインドされている間、バインドされたデータを再フォーマットする必要があるcustomConverterも、LostFocusイベントも正しく適用されません。エラーメッセージや警告が表示されず、コンバーターとイベントが呼び出されません。なぜ、どのようにこれを機能させることができるのか、誰か考えていますか?
アップデート:
この問題を解決するか、別のアプローチを試してみる必要があります。前回のテストでは、コンバーターをDataTemplateに直接追加しようとしましたが、うまくいきませんでした。生成されたコードは次のようになります。
<DataTemplate xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Conv="clr-namespace:my.Namespace" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid HorizontalAlignment="Stretch" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Conv:DecimalConverter x:Name="cnvDecimalConverter" />
</Grid.Resources>
<TextBlock Text="{Binding b0}" Grid.Column="0" />
<TextBox Text="{Binding b1, Converter={StaticResource cnvItemsDecimalConverter}}" HorizontalAlignment="Stretch" Grid.Column="1" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b2, Converter={StaticResource cnvItemsDecimalConverter}}" HorizontalAlignment="Stretch" Grid.Column="2" LostFocus="TxtAttribute_LostFocus" />
<TextBox Text="{Binding b3, Converter={StaticResource cnvItemsDecimalConverter}}" HorizontalAlignment="Stretch" Grid.Column="3" LostFocus="TxtAttribute_LostFocus" IsReadOnly="True" />
</Grid>
</DataTemplate>
何か案は?
アップデート2:
XamlReader.Load()がイベントをフックできないことがわかったので、Silverlightフォーラムでこのスレッドを参照してください
コンバーターは機能するはずですが、まだ見られない名前空間の問題があると思います。私は「単純な」ItemsControlアプローチでは選択肢がないので、ニーズを満たすための別の方法を探す時が来たと思います。