我有3个列表框,它们绑定了两个相同类型的3个独立的可观察集合。我的ViewModel具有通过属性公开的可观察集合。这是针对一些拖放分组,源列表框可以将项目拖动到两个不同的列表中。但我想让用户能够右键单击listboxitem并设置项目的属性。类型,名称等等。我正在使用数据模板,因为我希望所有三个框在功能上都相同。这很好用,当我点击单个项目没有问题时,我可以弹出上下文菜单。我的麻烦是我有一个名为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属性中如何获取observable集合中与所单击项目对应的项目。我有一个值转换器EnumToBoolean,它将位于绑定上以获取是否进行检查。问题是在可观察集合中设置/获取该特定项目的属性。
有什么想法?需要更多代码?需要我澄清一下吗?我有多近?顺便说一句,ViewModel代码是用VB 2010编写的。
由于 布莱斯
编辑: 我使用Angel的建议尝试了以下内容......
<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 vs 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 :(没有路径);的DataItem = NULL; target元素是'ContextMenu'(Name =''); target属性是'PlacementTarget'(类型'UIElement')
所以看起来绑定不起作用。有什么想法吗?
答案 0 :(得分:1)
ContextMenu
不是视觉树的一部分。因此,默认情况下,它不会将\ bind连接到应用它的TextBlock的datacontext ...
有两种方法可以做到这一点......
ContextMenu.PlacementTarget
并将其作为单个MenuItem绑定中的Path
引用。e.g。
<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>
所以在上面的例子中......你想要连接菜单项和文本框的数据上下文。因此,您需要在PlacementTarget
上定义ContextMenu
。此展示位置定位只能使用两种类型的绑定设置... ElementName
或StaticResource
。一旦上下文菜单通过PlacementTarget
连接到可视元素,请使用meuitem绑定中的Path
来解析数据上下文属性,即MyHeader
。
OR
使用代理元素方法......