views:

1379

answers:

2

I am inserting TreeViewItems into a TreeView control and setting the style for each at the time of insertion. I am assigning different styles (predefined in XAML), depending on the type of node (TreeViewItem) I want to insert. Some of the styles include a ContextMenu.

My problem is that I am unable to use Click="MyHandler" on the MenuItems; I get an error "root element requires a x:Class attribute to support event handlers in the XAML file." and apparently none of the elements within the Style block are root elements.

Any suggestions much appreciated.

XAML:

<Style x:Key="Terrain" TargetType="{x:Type TreeViewItem}">
   <Setter Property="HeaderTemplate">
      <Setter.Value>
         <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Canvas Background="{DynamicResource Terrain_icon}" />
                 <TextBlock Text="{Binding}" />
                 <StackPanel.ContextMenu>
                    <ContextMenu> 
                       <MenuItem Header="Edit..." Click="MyHandler"/> <!-- Error -->
                       <MenuItem Header="Add..."/>
                       <MenuItem Header="Delete"/>
                    </ContextMenu> 
                 </StackPanel.ContextMenu>
             </StackPanel>
          </DataTemplate>
        </Setter.Value>
     </Setter>
 </Style>

C#:

private void InsertTerrainNode(object sender, System.Windows.RoutedEventArgs e)
{
   // Add the new item under the first-level TreeViewItem
   TreeViewItem tvi = myTree.ItemContainerGenerator.ContainerFromItem(myTree.Items[0]) as TreeViewItem;
   TreeViewItem newTerrainNode = new TreeViewItem();
   newTerrainNode.Header = "Terrain";
   newTerrainNode.Style = (Style)this.FindResource("Terrain");
   tvi.Items.Insert(0,newTerrainNode);
}
+1  A: 

Use commands, create a class derived from ICommand, declare in the class that have access to user controles and is accessible in your xaml and bind button with that command. see here for detailes

ArsenMkrt
A: 

Another option is to add an event handler for the MenuItem.Click event to the TreeViewItem as you create it.

private void InsertTerrainNode(object sender, System.Windows.RoutedEventArgs e)
{
    // Add the new item under the first-level TreeViewItem
    TreeViewItem tvi = myTree.ItemContainerGenerator.ContainerFromItem(myTree.Items[0]) as TreeViewItem;
    TreeViewItem newTerrainNode = new TreeViewItem();
    newTerrainNode.Header = "Terrain";
    newTerrainNode.Style = (Style)this.FindResource("Terrain");
    newTerrainNode.AddHandler(MenuItem.Click, OnTreeItemContextMenuClicked);
    tvi.Items.Insert(0,newTerrainNode);
}

private void OnTreeItemContextMenuClicked(object sender, RoutedEventArgs e)
{
    // Handle the ContextMenu item click here
    // e.OriginalSource can be used to get the ContextMenu item clicked if needed.
}
Andy
Thanks Andy, this has got me on the right track I think. I now haveC#: newTerrainNode.ContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(OnTreeItemContextMenuClicked));However, I get a runtime error:Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at TreeTest2.MainWindow.InsertTerrainNode(Object sender, RoutedEventArgs e)Any thoughts?
What line in your event handler is throwing the exception?
Andy
When the event handler is added - newTerrainNode.AddHandler(MenuItem.Click, OnTreeItemContextMenuClicked);I thought it may be because the TreeViewItem hadn't been inserted into the tree at that point, but I get the same error (for the same line of code) if I add the handler after tvi.Items.Insert(0,newTerrainMode);
It's probably because newTerrainNode.ContextMenu is null. I think it should work if you call AddHandler() off of newTerrainNode.
Andy
Yeah, that's what I tried initially as per your code. No errors, but the OnTreeContextMenuClicked handler isn't fired when a context menu item is clicked.