0

我有 3 个列表框都绑定了两个相同类型的 3 个单独的可观察集合。我的 ViewModel 具有通过属性公开的可观察集合。这是一些拖放分组,源列表框可以将项目拖到两个不同的列表中。但我想让用户能够右键单击列表框并设置项目的属性。类型、名称等。我在其中使用数据模板,因为我希望所有三个框在功能上都相同。这很好用,当我单击单个项目时,我可以毫无问题地弹出上下文菜单。我的麻烦是我有一个名为 FieldType 的属性。它是一个具有 4 个潜在值的枚举。在我的一生中,我无法弄清楚如何将 MenuItem 的 IsChecked 属性绑定到该属性......无论如何在功能上。

<DataTemplate x:Key="SFTemplateWithContextMenu">
        <TextBlock Text="{Binding Path=FieldName}" ><!--Tag="{Binding DataContext, ElementName=Window}"-->
         <TextBlock.ContextMenu>
                <ContextMenu >
                    <ContextMenu.Resources>
                        <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverterc" />
                    </ContextMenu.Resources>
                    <MenuItem  Header="Rename..." />
                    <MenuItem Header="Field Type">
                        <MenuItem.Resources>
                            <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
                        </MenuItem.Resources>
                        <MenuItem  Header="String" IsCheckable="True" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.FieldType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverterc}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/>
                        <MenuItem  Header="Date" IsCheckable="True" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.FieldType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.Date}}"/>
                        <MenuItem  Header="Barcode" IsCheckable="True" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.FieldType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.BarCode}}" />
                    </MenuItem>
                </ContextMenu> 
            </TextBlock.ContextMenu>
        </TextBlock>
    </DataTemplate>

在上面的代码中,您可以在 String、Date 和 Barcode MenuItems 上看到我正在尝试做的事情(必须喜欢正在进行中的代码)。我的问题是它应该调用的暴露属性。我不知道如何在我的 ViewModel 属性中获取与单击的项目相对应的可观察集合中的项目。我有一个值转换器 EnumToBoolean 将位于绑定上以获取检查或不检查。问题是在可观察集合中设置/获取该特定项目的属性。

有什么想法吗?需要更多代码?需要我澄清什么吗?我离我有多近?顺便说一句,ViewModel 代码是用 VB 2010 编写的。

谢谢布莱斯

编辑:我使用天使的建议尝试了以下...

        <DataTemplate x:Key="SFTemplateWithContextMenu">
        <TextBlock x:Name="Field" Text="{Binding Path=FieldName}" >
         <TextBlock.ContextMenu PlacementTarget="{Binding ElementName=Field}">
                    <MenuItem  Header="Rename..." />
                    <MenuItem Header="Field Type">
                        <MenuItem.Resources>
                            <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
                        </MenuItem.Resources>
                        <MenuItem  Header="Date" IsCheckable="True" IsChecked="{Binding PlacementTarget.DataContext.FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/>
                    </MenuItem>
            </TextBlock.ContextMenu>
        </TextBlock>
    </DataTemplate>

但这给了我一个错误,上面写着......无法在属性元素上设置属性。不确定这是否是 TextBlox 与 TextBox 的问题?您在示例中使用了 TextBox ...我的猜测是您的代码也会这样做。所以我然后尝试了以下...

        <DataTemplate x:Key="SFTemplateWithContextMenu">
        <TextBlock x:Name="Field" Text="{Binding Path=FieldName}" ><!--Tag="{Binding DataContext, ElementName=Window}"-->
         <TextBlock.ContextMenu>
                <ContextMenu PlacementTarget="{Binding ElementName=Field}" >
                    <MenuItem  Header="Rename..." />
                    <MenuItem Header="Field Type">
                        <MenuItem.Resources>
                            <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
                        </MenuItem.Resources>
                        <MenuItem  Header="Date" IsCheckable="True" IsChecked="{Binding PlacementTarget.DataContext.FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/>
                    </MenuItem>
                </ContextMenu>
            </TextBlock.ContextMenu>
        </TextBlock>
    </DataTemplate>

但这会导致绑定错误... System.Windows.Data 错误:4:无法使用引用“ElementName = Field”找到绑定源。BindingExpression:(无路径);数据项=空;目标元素是'ContextMenu'(名称='');目标属性是“PlacementTarget”(类型“UIElement”)

所以看起来绑定不起作用。有什么想法吗?

4

1 回答 1

1

ContextMenu不是视觉树的一部分。因此,默认情况下,它不会连接 \ 绑定到应用它的 TextBlock 的数据上下文...

所以有两种方法可以做到这一点......

  1. 在单个 MenuItem 的绑定中设置ContextMenu.PlacementTarget并引用它。Path

例如

   <TextBox x:Name="MyTextBlock">
        <TextBox.ContextMenu PlacementTarget="{Binding ElementName=MyTextBlock}">
            <MenuItem 
                 Header="{Binding PlacementTarget.DataContext.MyHeader, 
                                  RelativeSource={RelativeSource
                                      AncestorType={x:Type ContextMenu}}}"
        </TextBox.ContextMenu>
  </TextBox>

所以在上面的例子中......你想菜单项与文本框的数据上下文连接起来。所以你PlacementTargetContextMenu. 此放置目标只能使用 2 种类型的绑定设置...ElementNameStaticResource. 并且一旦上下文菜单通过 连接到可视元素PlacementTarget,使用Pathmeuitem 的绑定中的 来解析数据上下文属性,即MyHeader

或者

使用代理元素方法...

绑定 datagrid 列可见性 MVVM

于 2012-05-16T13:37:01.050 回答