3

我正在使用 XamlReader.Parse(string) 动态构建我的数据模板。我遇到的问题是我无法在使用 XamlReader 创建的任何控件上放置任何事件。在网上做了一些研究后,我了解到这是 XamlReader 的一个已知限制。

我对 WPF 中的命令了解不多,但我能以某种方式使用它们来获得相同的结果吗?如果有怎么办?如果没有,有什么方法可以处理我的代码中的事件,该事件来自使用 Xaml Reader 创建的控件?

下面是我创建的数据模板的示例。我在将托管此数据模板的窗口的代码隐藏中定义了 MenuItem_Click 事件处理程序。

尝试运行它时出现以下错误: System.Windows.Markup.XamlParseException 未处理:无法从文本“MenuItem_Click”创建“单击”。

DataTemplate result = null;
        StringBuilder sb = new StringBuilder();

        sb.Append(@"<DataTemplate 
                        xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
                            <Grid Width=""Auto"" Height=""Auto"">

                            <TextBlock Text=""Hello"">
                                <TextBlock.ContextMenu>
                                    <ContextMenu>
                                         <MenuItem 
                                          Header=""World""
                                          Click=""MenuItem_Click""></MenuItem>
                                    </ContextMenu>
                                </TextBlock.ContextMenu>
                            </TextBlock>

                            </Grid>
                      </DataTemplate>");

        result = XamlReader.Parse(sb.ToString()) as DataTemplate;
4

2 回答 2

5

希望迟到的答案可能对其他人有所帮助:

我发现我需要在解析之后绑定事件,并且不得不从 Xaml 字符串中删除点击事件。

在我的场景中,我将生成的 DataTemplate 应用到 ItemTemplate,连接 ItemSource,然后添加处理程序。这确实意味着所有项目的点击事件都是相同的,但在我的情况下,标题是所需的信息并且方法是相同的。

//Set the datatemplate to the result of the xaml parsing.
myListView.ItemTemplate = (DataTemplate)result;

//Add the itemtemplate first, otherwise there will be a visual child error
myListView.ItemsSource = this.ItemsSource; 

//Attach click event.
myListView.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(MenuItem_Click));

然后单击事件需要返回到原始源,在我的情况下,发送者将是使用 DataTemplate 的 ListView。

internal void MenuItem_Click(object sender, RoutedEventArgs e){
    MenuItem mi = e.OriginalSource as MenuItem;
    //At this point you can access the menuitem's header or other information as needed.
}
于 2012-02-09T19:11:49.147 回答
0

看看这个链接。那里的大多数解决方案也将适用Parse。我不是真正的 C# 开发人员,所以我唯一能真正解释的是最后一个,这是一个 if-all-else-fails 选项:

首先,将 ID 添加到 XAML 而不是 Click 等属性。然后您可以使用FindLogicalNode获取节点,然后自己连接事件。

例如,假设您提供 MenuItem ID="WorldMenuItem"。然后在调用 parse 后的代码中,您可以执行以下操作:

MenuItem worldMenuItem = (MenuItem)LogicalTreeHelper.FindLogicalNode(result, "WorldMenuItem");
worldMenuItem.Click += MenuItem_Click; // whatever your handler is
于 2010-08-20T16:01:19.600 回答