2010-08-20 88 views
3

我使用XamlReader.Parse(字符串)动态构建数据模板。我遇到的问题是,我无法将任何事件放在使用XamlReader创建的任何控件上。在网上做了一些研究之后,我了解到这是XamlReader的一个已知限制。通过XamlReader使用事件/命令

我不知道很多关于WPF中的命令,但我可以用它们来获得相同的结果吗?如果是这样如何?如果没有,我可以通过使用Xaml Reader创建的控件来处理代码中的事件吗?

下面是我创建的datatemplate的一个示例。我有一个MenuItem_Click事件处理程序,它在将要托管这个数据模板的Window的代码隐藏中定义。

尝试运行时出现以下错误: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; 

回答

0

看看this link。那里的大多数解决方案也适用于Parse。我并不是真正的C#开发人员,所以我唯一真正可以解释的就是最后一个,这是一个if-all-else-failures选项:

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

例如,假设你给你的MenuItem ID="WorldMenuItem"。然后,在调用解析后,你的代码,你可以这样做:

MenuItem worldMenuItem = (MenuItem)LogicalTreeHelper.FindLogicalNode(result, "WorldMenuItem"); 
worldMenuItem.Click += MenuItem_Click; // whatever your handler is 
+0

我似乎无法得到该代码段进行编译。 FindLogicalNode接受一个DependencyObject,因为它是第一个参数,我无法弄清楚如何将一个DataTemplate转换为一个DependencyObject。有任何想法吗? – 2010-08-20 17:04:05

+0

我想我想出了如何从DataTemplate中获取DependencyObject ...我使用DataTemplate.LoadContent()。现在的问题是,无论MenuItem是什么都找不到。我知道上下文菜单并不包含在与其他控件相同的VisualTree中,对于LogicalTree也是如此? – 2010-08-20 17:38:58

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

然后单击事件需要得到回原始来源,发件人将在我的情况ListView中存在使用的DataTemplate。

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