1

我知道关于这个话题的答案很少。但他们都没有在我的情况下工作。

我有ListView一个风格和一个ItemContainerStyle。在 中,我定义了一些触发器,以便根据是否选择列表中的项目ItemContainer Style来使用不同的触发器。DataTemplate然后,最后在Datatemplate我有一个带有命令的上下文菜单。问题是如何将命令绑定到视图模型。

这是列表视图:

    <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>
4

3 回答 3

0

您可以使用相对来源:

  <ContextMenu x:Key="SelectedItemContextMenu">
            <MenuItem
            Header="Do Something"
            Command="{Binding Path=DataContext.DoSomethingCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
            </MenuItem>           
        </ContextMenu>
于 2012-07-27T21:34:05.897 回答
0

您的 ContextMenu 在数据模板中使用。我将被置于“LayoutRoot”的不同名称范围内,并且 ElementName 绑定将不起作用。此外,上下文菜单的 PlacementTarget 是边框,并且您没有在其上设置任何标签。所以第二个命令也不起作用。

看起来您正在 ListBox 级别(或 LayoutRoot?)上实现命令。将上下文菜单放在 ListBox 上可能更容易,并使用 ListBox.SelectedItem 来查找当前选择并将您的逻辑应用于其上。

于 2012-07-27T21:24:52.443 回答
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/

于 2012-07-28T08:09:12.337 回答