1

TreeView ContextMenu not fired events (ContextMenu Opened event not fire), I'm trying Caliburn.Micro.Telerik convention not solved problem.

TreeViewItemTemplate

    <HierarchicalDataTemplate x:Key="TreeViewItemTemplate" ItemsSource="{Binding Types}"
    ItemTemplateSelector="{StaticResource NamespaceItemTemplateSelector}">
<StackPanel Orientation="Horizontal">
    <Path
            Data=""
            Height="11.458" Margin="0,0,5,0" RenderTransformOrigin="0.5,0.5" Stretch="Fill"
            UseLayoutRounding="False" Width="11.264">
        <Path.Fill>
            <SolidColorBrush Color="#FF333333">
                <SolidColorBrush.RelativeTransform>
                    <MatrixTransform Matrix="Identity" />
                </SolidColorBrush.RelativeTransform>
                <SolidColorBrush.Transform>
                    <MatrixTransform Matrix="Identity" />
                </SolidColorBrush.Transform>
            </SolidColorBrush>
        </Path.Fill>
        <Path.RenderTransform>
            <TransformGroup>
                <ScaleTransform />
                <SkewTransform />
                <RotateTransform />
                <TranslateTransform />
            </TransformGroup>
        </Path.RenderTransform>
    </Path>
    <TextBlock Text="{Binding Header}" Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}">
   <TextBlock.ContextMenu>
 <ContextMenu cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self},Path=UIElement.Tag}" cal:Message.Attach="[Event Opened] = [Action Opened($dataContext)]" >
       <MenuItem Header="NewChild" cal:Message.Attach="NewChild($datacontext)"/>
         </ContextMenu>
  </TextBlock.ContextMenu>
    </TextBlock>
</StackPanel>

TreeView

<TreeView x:Name="TreeView" ItemTemplate="{StaticResource TreeViewItemTemplate}" ItemsSource="{Binding Source}"/>
Cipher
  • 352
  • 1
  • 11
  • Is your problem with the event not firing or Caliburn.Micro's conventions not working with your context menu ? – Ibrahim Najjar Jul 16 '13 at 10:01
  • Thanks for reply, Caliburn.Micro conventions worked but ContextMenu and MenuItem events not firing. – Cipher Jul 16 '13 at 10:53
  • @Sniffer It does not have any solution? If your want upload project. Please help me. Thanks. – Cipher Jul 17 '13 at 07:08
  • I wish to help you but the problem is that you are using Telerik controls which i don't have a license for. If you can replicate this problem with the WPF `TreeView` control and then upload a version i will look into it. – Ibrahim Najjar Jul 17 '13 at 09:40
  • Thanks for reply, This issue exist in standard ContectMenu, Edit first post to standard ContextMenu. – Cipher Jul 17 '13 at 09:45
  • I would really appreciate if you could upload the broken project because i don't have time to modify your version. – Ibrahim Najjar Jul 17 '13 at 09:47
  • Uplod file, http://bayfiles.net/file/STqD/MekWE9/TreeViewSample.rar – Cipher Jul 17 '13 at 10:43
  • After click MenuItem not fired and this error, at Caliburn.Micro.ActionMessage.Invoke(Object eventArgs) at System.Windows.Interactivity.TriggerAction.CallInvoke(Object parameter) at System.Windows.Interactivity.TriggerBase.InvokeActions(Object parameter) at System.Windows.Interactivity.EventTriggerBase.OnEvent(EventArgs eventArgs) at System.Windows.Interactivity.EventTriggerBase.OnEventImpl(Object sender, EventArgs eventArgs) – Cipher Jul 17 '13 at 13:57
  • I am sorry but there is a problem with the site you have uploaded the sample to, can you please upload it to [4shared](4shared.com) ? – Ibrahim Najjar Jul 17 '13 at 15:09
  • Thanks for taking time, http://www.4shared.com/rar/wqVPUw1Z/TreeViewSample.html – Cipher Jul 17 '13 at 16:12
  • OK @stevequeen, i am sorry for not replying quickly as i was so tiered yesterday. Nevertheless i have found the problem and will give you the solution. – Ibrahim Najjar Jul 18 '13 at 09:56

1 Answers1

4

Before i tell you what was the problem i want to point out that the version of the code you uploaded is a bit different than the one you posted in your question.

OK, The problem lies exactly in this section of the template:

<TextBlock Text="{Binding Header}" Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}">
    <TextBlock.ContextMenu>
        <ContextMenu cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self},Path=UIElement.Tag}" cal:Message.Attach="[Event Opened] = [Action Opened($dataContext)]" >
            <MenuItem Header="NewChild" cal:Message.Attach="NewChild($datacontext)"/>
        </ContextMenu>
    </TextBlock.ContextMenu>
</TextBlock>

To fix it you need to replace it with this modified version:

<TextBlock Text="{Binding Header}" Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}">
    <TextBlock.ContextMenu>
        <ContextMenu cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Tag}" cal:Message.Attach="[Event Opened] = [Action ContextMenuOpened($source)]">
            <MenuItem Header="New" cal:Message.Attach="[Event Click] = [Action ClickMenuItem($source)]"/>
        </ContextMenu>
    </TextBlock.ContextMenu>
</TextBlock>

The problem was caused by three issues:

  1. In the template and specifically in this line of code <ContextMenu cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self},Path=UIElement.Tag}" the Path=UIElement.Tag was causing a binding error because there is no property on type ContextMenu that is called UIElement. Instead you have to replace that with the PlacementTarget property which represents the element in the user interface on which the context menu was opened.
  2. The second issue is that you were putting the methods that handle those events on the wrong class. They shouldn't be on the ShellViewModel because in the template you are setting the Action.Target to be the DataContext behind the TextBlock which is actually the NamespaceViewModel in your situation, so the methods should go on the NamespaceViewModel.
  3. The third and final issue is that your methods had the wrong signature so they couldn't be found by Caliburn.Micro. What i mean is that you are declaring your ContextMenuOpened method like this: void ContextMenuOpened(sender args, RoutedEventArgs args); but in the template you are calling the method like this: [Action ContextMenuOpened($source)] which sends the method the FrameworkElement that caused the event (ContextMenu in this case), so you should change the method signature for this event to this: void ContextMenuOpened(ContextMenu source) or the more general void ContextMenuOpened(FrameworkElement source).

Summary:

  1. Fix your template to use the PlacementTarget property.
  2. Move your methods to NamespaceViewModel.
  3. Fix your methods signatures.

Finally: If you want to know everything about actions and action messages and what parameters get passed to what then you should really read the documentation wiki about Actions.

Ibrahim Najjar
  • 19,178
  • 4
  • 69
  • 95