我正在使用XamlReader.Parse(string)动态构建我的datatemplate。我遇到的问题是我无法在使用XamlReader创建的任何控件上放置任何事件。在网上做了一些研究后,我了解到这是XamlReader的一个已知限制。
我对WPF中的命令知之甚少,但是我能以某种方式使用它们来获得相同的结果吗?如果是这样的话?如果没有,我有什么办法可以在使用Xaml Reader创建的控件中处理我的代码中的事件吗?
以下是我创建的datatemplate的示例。我有窗口的代码隐藏中定义的MenuItem_Click事件处理程序将托管此datatemplate。
尝试运行时出现以下错误:System.Windows.Markup.XamlParseException未处理:无法从文本'MenuItem_Click'创建'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;
答案 0 :(得分:5)
希望迟到的答案可能有助于其他人:
我发现我需要在解析后绑定事件,并且必须从Xaml字符串中删除click事件。
在我的场景中,我将生成的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.
}
答案 1 :(得分:0)
看看this link。大多数解决方案也适用于Parse
。我不是一个真正的C#开发者,所以我唯一可以解释的是最后一个,这是一个if-all-else-failed选项:
首先,您将ID添加到XAML而不是Click,etc属性。然后,您可以使用FindLogicalNode获取节点,然后自己连接事件。
例如,假设您提供了MenuItem ID="WorldMenuItem"
。然后在调用解析后的代码中,您可以这样做:
MenuItem worldMenuItem = (MenuItem)LogicalTreeHelper.FindLogicalNode(result, "WorldMenuItem");
worldMenuItem.Click += MenuItem_Click; // whatever your handler is