让我们从场景开始:
我在UserControl中有一个ItemsControl。在这个ItemsControl中,我有一个动态创建的DataTemplate,它是在codebehind中创建和添加的。由于似乎没有一种很好的方法在代码隐藏中创建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中添加Converter,但我没有运气。生成的代码现在看起来像这样:
<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()只是无法挂钩事件。见this Thread in the Silverlight Forums
转换器应该可以工作,我想我还有一些我没看到的命名空间问题。我的“简单”ItemsControl方法让我有点不习惯,所以我认为是时候寻找另一种方法来满足我的需求了。
答案 0 :(得分:0)
只是为了清除这种情况:通过生成xaml字符串并从中提取控件,无法通过事件生成动态DataTemplate。使用事件解析xaml代码的唯一选择是通过Application.LoadComponent,它需要一个URI才能工作。
我最终使用嵌套的ItemControl来创建我的“动态”行为。