2010-08-20 27 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. 
}