我知道这个主题的答案很少。但是他们都没有在我的案件中工作。
我有一个ListView
样式和ItemContainerStyle
。在ItemContainer
Style
中,我定义了一些触发器,以便使用不同的DataTemplate
,具体取决于是否选择了列表中的项目。然后,最后在Datatemplate
我有一个带命令的上下文菜单。问题是如何将命令绑定到viewmodel。
这是ListView:
<ListView
x:Name="lstPersons"
Grid.Row="1"
Style="{StaticResource ListViewStyle}"
ItemContainerStyle="{StaticResource ItemContainerStyle}"
DataContext="{Binding}"
ItemsSource="{Binding Path=Persons}"
Tag="{Binding}"
SelectedItem="{Binding Path=SelectedPerson, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ListView>
这些是样式,数据窗口和上下文菜单(在资源字典中定义)。 上下文菜单中的命令不起作用....:
<ContextMenu x:Key="SelectedItemContextMenu">
<MenuItem
Header="Do Something"
Command="{Binding Path=DataContext.DoSomethingCmd, ElementName=LayoutRoot}">
</MenuItem>
<MenuItem
Header="Do Something"
Command="{Binding PlacementTarget.Tag.DoSomethingCmd, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
</MenuItem>
</ContextMenu>
<DataTemplate
x:Key="ItemTemplate">
<Canvas
Margin="4"
Width="60"
Height="60"
Background="LightGray">
<TextBlock
Foreground="Black"
Margin="2 0 0 0"
Opacity="0.5"
FontFamily="Segoe UI"
Text="{Binding Path=FirstName}" />
</Canvas>
</DataTemplate>
<DataTemplate
x:Key="ItemSelectedTemplate">
<Grid>
<Border
BorderBrush="Black"
BorderThickness="1"
Margin="3"
ContextMenu="{DynamicResource SelectedItemContextMenu}">
<Canvas
Width="60"
Height="60"
Background="LightBlue">
<TextBlock
Foreground="Black"
Margin="2 0 0 0"
Opacity="0.5"
FontFamily="Segoe UI"
Text="{Binding Path=FirstName}" />
</Canvas>
</Border>
</Grid>
</DataTemplate>
<!--style of the listviewitem-->
<Style
TargetType="{x:Type ListViewItem}"
x:Key="ItemContainerStyle">
<Setter
Property="ContentTemplate"
Value="{StaticResource ItemTemplate}" />
<Style.Triggers>
<Trigger
Property="IsSelected"
Value="True">
<Setter
Property="ContentTemplate"
Value="{StaticResource ItemSelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
<!--style of the listview-->
<Style
TargetType="{x:Type ListBox}"
x:Key="ListViewStyle">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type ListBox}">
<Grid>
<Border>
<ScrollViewer
Focusable="false">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"/>
</ScrollViewer>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
答案 0 :(得分:0)
您的ContextMenu在数据模板中使用。我将被置于“LayoutRoot”的不同名称范围,并且ElementName绑定将不起作用。此外,上下文菜单的PlacementTarget是Border,并且您没有在其上设置任何Tag。所以第二个命令也不起作用。
看起来你是在ListBox级别(或LayoutRoot?)上实现命令。将上下文菜单放在ListBox上可能更容易,并使用ListBox.SelectedItem查找当前选择并在其上应用逻辑。
答案 1 :(得分:0)
您可以使用RelativeSource:
<ContextMenu x:Key="SelectedItemContextMenu">
<MenuItem
Header="Do Something"
Command="{Binding Path=DataContext.DoSomethingCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
</MenuItem>
</ContextMenu>
答案 2 :(得分:0)
在这种情况下,您可能应该使用RoutedCommands而不是VM命令。您可以将RoutedCommand绑定到ContextMenu,并且因为您只需要静态对象引用,所以找到它们应该不是问题。然后,您应该在应该处理命令的控件上设置适当的CommandBindings(ListView或ListViewItem,具体取决于您是希望List-ViewModel还是Item-ViewModel来处理命令)。这些控件将知道它们的ViewModel,因此绑定它们不会成为问题。通过WPF中内置的命令路由过程,上下文菜单将自动为其命令找到正确的目标。
有关如何以MVVM友好方式设置CommandBindings的指导,您可能需要参考http://wpfglue.wordpress.com/2012/05/07/commanding-binding-controls-to-methods/