找不到用于引用绑定的来源' RelativeSource FindAncestor,AncestorType =' System.Windows.Controls.UserControl',AncestorLevel =' 1''

时间:2018-03-23 10:04:30

标签: c# wpf mvvm

我正在尝试根据MVVM中的hierarchicaldatatemplate在树视图中设置上下文菜单。 根是一个父视图模型,它在可观察集合中嵌套了视图模型,依此类推。根目录在我的主视图模型

示例:

      • Grand Child 1
      • Grand Child 2
    • 孩子2
      • Grand Child 1
    • 儿童3

我尝试做的是在Grand Child上设置一个名为" Delete"的上下文菜单。我遇到的问题是当它位于子视图模型中时,如何在上下文菜单中设置命令?因为所有Grand孩子都存储在子视图模型中的observablecollection中。 我尝试了几个在这里发布的解决方案,但对我没用。

到目前为止我尝试了什么:

  • 使用Tag属性和Placementtarget

但我收到了错误:

找不到用于引用绑定的源' RelativeSource FindAncestor,AncestorType =' SimTableApplication.View.Controls.VirtualControllerView',AncestorLevel =' 1''。 BindingExpression :(没有路径);的DataItem = NULL;目标元素是' StackPanel' (名称='&#39);目标财产是'标记' (键入'对象')

这是我的树视图的xaml代码:

 <TreeView Name="Tree" ItemsSource="{Binding Projects}" Background="#cccccc" BorderThickness="0" >
                    <i:Interaction.Behaviors>
                        <behav:TreeViewSelectedItemBehavior SelectedItem="{Binding SelectedTreeViewItem}"/>
                    </i:Interaction.Behaviors>
                    <TreeView.Resources>
                        <Style TargetType="TreeViewItem">
                            <Setter Property="IsExpanded" Value="True"/>
                            <Setter Property="Foreground" Value="White"/>
                            <Setter Property="FontWeight" Value="Bold"/>
                            <Setter Property="Background" Value="Transparent"/>
                            <EventSetter Event="MouseRightButtonDown" Handler="TreeViewItem_MouseRightButtonDown"/>
                        </Style>                        
                    </TreeView.Resources>
                    <TreeView.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding VirtualPLCs}">
                            <StackPanel Orientation="Horizontal">
                                <Image Source="/SimTableApplication;component/Assets/ICO_PE_Project.ico" Height="18" Width="18"/>
                                <TextBlock Text="{Binding ProjModel.ProjectName}" Margin="3"/>
                                <StackPanel.ContextMenu>
                                    <ContextMenu>
                                        <MenuItem Header="Add new Controller" Command="{Binding AddNewControllerCommand}">
                                            <MenuItem.Icon>
                                                <Image Source="/SimTableApplication;component/Assets/ICO_PE_CreateNewItem.ico"/>
                                            </MenuItem.Icon>
                                        </MenuItem>
                                        <Separator />
                                        <MenuItem Header="Properties" Command="{Binding ShowProjectPropertiesCommand}">
                                            <MenuItem.Icon>
                                                <Image Source="/SimTableApplication;component/Assets/ICO_PVS_Properties.png"/>
                                            </MenuItem.Icon>
                                        </MenuItem>
                                    </ContextMenu>
                                </StackPanel.ContextMenu>
                            </StackPanel>
                            <HierarchicalDataTemplate.ItemTemplate>
                                <HierarchicalDataTemplate ItemsSource="{Binding SimTables}">
                                    <StackPanel Orientation="Horizontal">
                                        <Image Source="/SimTableApplication;component/Assets/ICO_PE_Device.ico" Height="18" Width="18"/>
                                        <TextBlock Text="{Binding Name}" Margin="3"/>
                                        <StackPanel.ContextMenu>
                                            <ContextMenu>
                                                <MenuItem Header="Add new SIM table" Command="{Binding AddNewSimTableCommand}">
                                                    <MenuItem.Icon>
                                                        <Image Source="/SimTableApplication;component/Assets/ICO_PE_CreateNewItem.ico"/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                                <Separator />
                                                <MenuItem Header="Power On" Command="{Binding PowerOnCommand}">
                                                    <MenuItem.Icon >
                                                        <Image Source="/SimTableApplication;component/Assets/ICO_PLCSIM_Tbon.ico "/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                                <MenuItem Header="Power Off" Command="{Binding PowerOffCommand}">
                                                    <MenuItem.Icon >
                                                        <Image Source="/SimTableApplication;component/Assets/ICO_PLCSIM_Tboff.ico "/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                                <MenuItem Header="Run" Command="{Binding RunCommand}">
                                                    <MenuItem.Icon >
                                                        <Image Source="/SimTableApplication;component/Assets/StartSimulation.png"/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                                <MenuItem Header="Stop" Command="{Binding StopCommand}">
                                                    <MenuItem.Icon >
                                                        <Image Source="/SimTableApplication;component/Assets/StopSimulation.png"/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                                <MenuItem Header="MRES" Command="{Binding ResetMemoryCardCommand}">
                                                    <MenuItem.Icon >
                                                        <Image Source="/SimTableApplication;component/Assets/reset-icon.png"/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                                <Separator />
                                                <MenuItem Header="Delete">
                                                    <MenuItem.Icon>
                                                        <Image Source="/SimTableApplication;component/Assets/ICO_PE_TbDelete.ico"/>
                                                    </MenuItem.Icon>
                                                </MenuItem>
                                            </ContextMenu>
                                        </StackPanel.ContextMenu>
                                    </StackPanel>
                                    <HierarchicalDataTemplate.ItemTemplate >
                                        <DataTemplate >
                                            <StackPanel Orientation="Horizontal" **Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">**
                                                <Image Source="/SimTableApplication;component/Assets/ICO_PLCS_SimTable.ico" Height="18" Width="18"/>
                                                <TextBlock  Text="{Binding SimTableName}"  Margin="3"/>
                                                <StackPanel.ContextMenu>
                                                    <ContextMenu>
                                                        <MenuItem Header="Delete"  Command="{Binding Path=PlacementTarget.Tag.DataContext.DeleteSimTableCommand,
                                                    RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}">
                                                            <MenuItem.Icon>
                                                                <Image Source="/SimTableApplication;component/Assets/ICO_PE_TbDelete.ico"/>
                                                            </MenuItem.Icon>
                                                        </MenuItem>
                                                    </ContextMenu>
                                                </StackPanel.ContextMenu>
                                            </StackPanel>
                                        </DataTemplate>
                                    </HierarchicalDataTemplate.ItemTemplate>
                                </HierarchicalDataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>

                </TreeView>

也许有人可以给我一个提示我做错了什么。

1 个答案:

答案 0 :(得分:0)

我认为您的问题是因为您正在尝试同时执行relativesource绑定以及placementtarget。我认为我没有设法按预期工作。 我通常做的是将placementtarget的标签绑定到我要从哪里获取命令,然后我就可以实现。如果您在该上下文菜单中有其他命令,则可能会出现问题,但您却没有。 我没有你所有的代码,所以我只用两个级别 - 父母和孩子一起扔东西。 Child是叶子,父级等同于删除命令的位置。 这对我有用:

<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <TreeView ItemsSource="{Binding Parents}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:Parent}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:Child}">
                <StackPanel Tag="{Binding DataContext, 
                        RelativeSource={RelativeSource AncestorType=TreeViewItem , AncestorLevel=2}
                        }" 
                       >
                    <StackPanel.ContextMenu>
                        <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag,
                                     RelativeSource={x:Static RelativeSource.Self}}">
                            <MenuItem Header="Delete"  Command="{Binding DeleteCommand}">
                            </MenuItem>
                        </ContextMenu>
                    </StackPanel.ContextMenu>
                    <TextBlock Text="{Binding ChildName}"/>
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>
</Grid>

标签位于可视化树中,因此它可以执行相对来源的操作,然后命令位于放置目标的标记中。 如果不清楚,我可以发布样本。

删除时的键绑定会更简单,我想这对你没有好处。