Caliburn.micro通过contextmenu onclick

时间:2019-01-27 04:32:21

标签: c# wpf treeview contextmenu caliburn.micro

我的任务是在treeview中使用contextmenu,然后通过单击contextmenu元素将选定的treeview的项目传递给ViewModel。

这是我的xaml:

<Window.Resources>
  <HierarchicalDataTemplate x:Key="Ufps"
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Id}" />
            <TextBlock Margin="5 0 0 0" Text="{Binding Name}" />
        </StackPanel>
  </HierarchicalDataTemplate>
</Window.Resources>
........
........
<TreeView x:Name="TrvUfpsDictionary" Height="222" Canvas.Left="25" 
  Canvas.Top="280" Width="545"
  Background="AliceBlue" 
  ItemsSource="{Binding Path=Ufps, Mode=OneWay}" 
  ItemTemplate="{StaticResource Ufps}">
        <TreeView.ContextMenu>
          <ContextMenu>
            <MenuItem Header="Add Element"
             cal:Message.Attach="[Event Click] = [Action AddElement(TrvUfpsDictionary.SelectedItem)]"
                />
                ................
            </ContextMenu>
        </TreeView.ContextMenu>           
    </TreeView>
........
<Button Content="Test" Canvas.Left="475" Canvas.Top="568" Width="75"
 cal:Message.Attach="[Event Click] = [Action AddElement(TrvUfpsDictionary.SelectedItem)]"/>

这是简单的ViewModel代码:

  public class UserSettingsViewModel : PropertyChangedBase
  {
   ..........

   public void AddElement(object selectedItem)
    {         
       MessageBox.Show("Element added! "+selectedItem.?GetHashCode());            
    }
   ..........
  }

现在,我坚持使用它。当我选择了treeview的项目,然后按下“测试”按钮时-它工作正常,它将选择的项目传递给我的VM中的“ AddElement”。但是,当我对contextmenu进行相同操作时-它始终传递null。我错过了什么吗?

编辑 我做了一个简单的应用程序,描述了问题。 https://github.com/whizzzkey/WpfApp1

1 个答案:

答案 0 :(得分:1)

您可能必须将“上下文菜单”进一步移至TreeView,“项目模板”,然后将“上下文菜单”添加到节点中具有的Label / TextBlock。

例如,考虑下面的雇员树(由于我不知道您的数据结构,因此是模拟的),

<TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Positions}" >
                    <Label Content="{Binding DepartmentName}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Employees}" >
                            <Label Content="{Binding PositionName}"  Tag="{Binding DataContext, ElementName=TestControl}" >
                                <Label.ContextMenu>
                                    <ContextMenu cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                                        <MenuItem Header="Add Element" cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]"/>
                                    </ContextMenu>
                                </Label.ContextMenu>
                            </Label>
                            <HierarchicalDataTemplate.ItemTemplate>
                                <DataTemplate>
                                    <Label Content="{Binding EmployeeName}" Tag="{Binding DataContext, ElementName=TestControl}">
                                        <Label.ContextMenu>
                                            <ContextMenu cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                                                <MenuItem Header="Add Element" cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]"
                />
                                            </ContextMenu>
                                        </Label.ContextMenu>
                                    </Label>
                                </DataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>

这里有几点要注意的要点。由于您的方法存在于ViewModel中,因此您必须确保DataContext指向的是ViewModel而不是绑定到节点的Item Type。

为此,您需要使用cal:Action.TargetWithoutContext。标签定义的下一行确保我们可以访问视图的DataContext。

Tag="{Binding DataContext, ElementName=TestControl}" 

以下行可确保我们正确绑定到ViewModel。 TestControl是您的UserControl的x:Name

cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"

最后,点击操作将进行如下修改。

cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]"

这将确保通过正确的参数调用ViewModel的Action。

更新

根据您的注释和代码,以下是所需的更改。

窗口定义:添加x:Name

<Window
        x:Class="WpfApp1.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.caliburnproject.org"
        Title="XmlData Tree Test"
        x:Name="TestControl"
        Width="250"
        Height="350"
        >

根分层模板 将Item来源和Tag关联起来放置在TextBlock上,相对来源也具有Self。

<HierarchicalDataTemplate DataType="root" ItemsSource="{Binding XPath=./*}" >
            <StackPanel Orientation="Horizontal">
                <TextBlock Margin="0" Text="ROOT"  Tag="{Binding DataContext, ElementName=TestControl}">
                    <TextBlock.ContextMenu>
                        <ContextMenu
                        cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                            <MenuItem Header="Add Element" cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]" />
                        </ContextMenu>
                    </TextBlock.ContextMenu>
                    </TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>

节点的分层模板

<HierarchicalDataTemplate DataType="Node"
                                  ItemsSource="{Binding XPath=./*}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Margin="0"
                           Text="Node:" />
                <TextBlock Margin="5,0,0,0"  Tag="{Binding DataContext, ElementName=TestControl}"
                           Text="{Binding XPath=@name}" >
                    <TextBlock.ContextMenu>
                        <ContextMenu
                            cal:Action.TargetWithoutContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                            <MenuItem Header="Add Element" cal:Message.Attach="[Event Click] = [Action AddElement($datacontext)]" />
                        </ContextMenu>
                    </TextBlock.ContextMenu>
                </TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>

输出示例 对于根

enter image description here

对于Node, enter image description here