代码隐藏中生成的 DataTemplate 中的 EventBinding

发布于 2024-07-15 17:20:57 字数 3624 浏览 5 评论 0原文

让我们从场景开始:

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

lets begin with the scenario:

I have an ItemsControl inside a UserControl. In this ItemsControl I have a dynamicly created DataTemplate which is created and added in codebehind. As there doesn't seem to be a nice way to create a DataTemplate in codebehind I had to programmatically generate the xaml code for my DataTemplate into a string and then create a DataTemplate object out of it through XamlReader:

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;

The generated XAML code looks like this and is actually used (the items get rendered as expected):

<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>

In case you wonder: the xmlns attribute is needed by the XamlReader to render the control, else you'll get an exception when reaching the code.

My problem:

now while the items look like expected and data is correctly bound neither my customConverter that should reformat the bound data, nor the LostFocus event are correctly applied. I don't get any error messages or warnings, converter and event just don't get called. Anyone an idea why and how I can get this to work?

Update:

I reached a point where I have to solve this problem or to try a different approach.
In my last tests I tried to add the Converter directly in the DataTemplate but I had no luck. The generated code now looks like this:

<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>

Any ideas?

Update 2:

As I just found out XamlReader.Load() just is not able to hook up events. See this Thread in the Silverlight Forums

The Converters should work, I guess I still have some kind of namespace problem I don't see. I'm kind of out of options with my "simple" ItemsControl approach so I think it's time to look for another method to reach my needs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一桥轻雨一伞开 2024-07-22 17:20:57

只是为了澄清情况:不可能通过生成 xaml 字符串来生成带有事件的动态 DataTemplate 并从中提取控件。 使用事件解析 xaml 代码的唯一选项是通过 Application.LoadComponent,它需要 URI 才能工作。

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

Just to clear up the situation: It is not possible to generate dynamic DataTemplates with events through generating an xaml string and extract the control from this. The only option to parse xaml code with events is through Application.LoadComponent which needs a URI to work.

I ended up using nested ItemControls to create my "dynamic" behaviour.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文