事件绑定在生成的DataTemplate后面的代码中

时间:2009-03-27 16:28:54

标签: c# .net silverlight-2.0 datatemplate xmlwriter

让我们从场景开始:

我在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方法让我有点不习惯,所以我认为是时候寻找另一种方法来满足我的需求了。

1 个答案:

答案 0 :(得分:0)

只是为了清除这种情况:通过生成xaml字符串并从中提取控件,无法通过事件生成动态DataTemplate。使用事件解析xaml代码的唯一选择是通过Application.LoadComponent,它需要一个URI才能工作。

我最终使用嵌套的ItemControl来创建我的“动态”行为。